Merge branch 'kk/streaming-walk-pqueue' into kk/no-walk-pathspec-fix
* kk/streaming-walk-pqueue: (280 commits) revision: use priority queue for non-limited streaming walks revision: introduce rev_walk_mode to clarify get_revision_1() pack-objects: call release_revisions() after cruft traversal The 9th batch The 8th batch The 7th batch Start preparing for 2.54.1 The 6th batch send-pack: pass negotiation config in push remote: add remote.*.negotiationInclude config fetch: add --negotiation-include option for negotiation negotiator: add have_sent() interface remote: add remote.*.negotiationRestrict config transport: rename negotiation_tips fetch: add --negotiation-restrict option t5516: fix test order flakiness repack: allow `--write-midx=incremental` without `--geometric` repack: introduce `--write-midx=incremental` repack: implement incremental MIDX repacking packfile: ensure `close_pack_revindex()` frees in-memory revindex ...main
commit
bd2943265e
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
jobname: ClangFormat
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ jobs:
|
|||
check-whitespace:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@ jobs:
|
|||
COVERITY_LANGUAGE: cxx
|
||||
COVERITY_PLATFORM: overridden-below
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: install minimal Git for Windows SDK
|
||||
if: contains(matrix.os, 'windows')
|
||||
uses: git-for-windows/setup-git-for-windows-sdk@v1
|
||||
uses: git-for-windows/setup-git-for-windows-sdk@v2
|
||||
- run: ci/install-dependencies.sh
|
||||
if: contains(matrix.os, 'ubuntu') || contains(matrix.os, 'macos')
|
||||
env:
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ jobs:
|
|||
cat git-po-helper.out
|
||||
exit $exit_code
|
||||
- name: Create comment in pull request for report
|
||||
uses: mshick/add-pr-comment@v2
|
||||
uses: mshick/add-pr-comment@v3
|
||||
if: >-
|
||||
always() &&
|
||||
github.event_name == 'pull_request_target' &&
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ jobs:
|
|||
echo "skip_concurrent=$skip_concurrent" >>$GITHUB_OUTPUT
|
||||
- name: skip if the commit or tree was already tested
|
||||
id: skip-if-redundant
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v9
|
||||
if: steps.check-ref.outputs.enabled == 'yes'
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
|
|
@ -112,8 +112,8 @@ jobs:
|
|||
group: windows-build-${{ github.ref }}
|
||||
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v1
|
||||
- uses: actions/checkout@v6
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v2
|
||||
- name: build
|
||||
shell: bash
|
||||
env:
|
||||
|
|
@ -123,7 +123,7 @@ jobs:
|
|||
- name: zip up tracked files
|
||||
run: git archive -o artifacts/tracked.tar.gz HEAD
|
||||
- name: upload tracked files and build artifacts
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: windows-artifacts
|
||||
path: artifacts
|
||||
|
|
@ -140,14 +140,14 @@ jobs:
|
|||
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
|
||||
steps:
|
||||
- name: download tracked files and build artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: windows-artifacts
|
||||
path: ${{github.workspace}}
|
||||
- name: extract tracked files and build artifacts
|
||||
shell: bash
|
||||
run: tar xf artifacts.tar.gz && tar xf tracked.tar.gz
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v1
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v2
|
||||
- name: test
|
||||
shell: bash
|
||||
run: . /etc/profile && ci/run-test-slice.sh $((${{matrix.nr}} + 1)) 10
|
||||
|
|
@ -157,7 +157,7 @@ jobs:
|
|||
run: ci/print-test-failures.sh
|
||||
- name: Upload failed tests' directories
|
||||
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: failed-tests-windows-${{ matrix.nr }}
|
||||
path: ${{env.FAILED_TEST_ARTIFACTS}}
|
||||
|
|
@ -173,10 +173,10 @@ jobs:
|
|||
group: vs-build-${{ github.ref }}
|
||||
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v1
|
||||
- uses: actions/checkout@v6
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v2
|
||||
- name: initialize vcpkg
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: 'microsoft/vcpkg'
|
||||
path: 'compat/vcbuild/vcpkg'
|
||||
|
|
@ -186,7 +186,7 @@ jobs:
|
|||
repository: git/git
|
||||
definitionId: 9
|
||||
- name: add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
- name: copy dlls to root
|
||||
shell: cmd
|
||||
run: compat\vcbuild\vcpkg_copy_dlls.bat release
|
||||
|
|
@ -208,7 +208,7 @@ jobs:
|
|||
- name: zip up tracked files
|
||||
run: git archive -o artifacts/tracked.tar.gz HEAD
|
||||
- name: upload tracked files and build artifacts
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: vs-artifacts
|
||||
path: artifacts
|
||||
|
|
@ -224,9 +224,9 @@ jobs:
|
|||
group: vs-test-${{ matrix.nr }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
|
||||
steps:
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v1
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v2
|
||||
- name: download tracked files and build artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: vs-artifacts
|
||||
path: ${{github.workspace}}
|
||||
|
|
@ -244,7 +244,7 @@ jobs:
|
|||
run: ci/print-test-failures.sh
|
||||
- name: Upload failed tests' directories
|
||||
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: failed-tests-windows-vs-${{ matrix.nr }}
|
||||
path: ${{env.FAILED_TEST_ARTIFACTS}}
|
||||
|
|
@ -258,7 +258,7 @@ jobs:
|
|||
group: windows-meson-build-${{ github.ref }}
|
||||
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
- name: Set up dependencies
|
||||
shell: pwsh
|
||||
|
|
@ -270,7 +270,7 @@ jobs:
|
|||
shell: pwsh
|
||||
run: meson compile -C build
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: windows-meson-artifacts
|
||||
path: build
|
||||
|
|
@ -286,13 +286,13 @@ jobs:
|
|||
group: windows-meson-test-${{ matrix.nr }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
- name: Set up dependencies
|
||||
shell: pwsh
|
||||
run: pip install meson ninja
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: windows-meson-artifacts
|
||||
path: build
|
||||
|
|
@ -305,7 +305,7 @@ jobs:
|
|||
run: ci/print-test-failures.sh
|
||||
- name: Upload failed tests' directories
|
||||
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: failed-tests-windows-meson-${{ matrix.nr }}
|
||||
path: ${{env.FAILED_TEST_ARTIFACTS}}
|
||||
|
|
@ -341,7 +341,7 @@ jobs:
|
|||
TEST_OUTPUT_DIRECTORY: ${{github.workspace}}/t
|
||||
runs-on: ${{matrix.vector.pool}}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- run: ci/install-dependencies.sh
|
||||
- run: ci/run-build-and-tests.sh
|
||||
- name: print test failures
|
||||
|
|
@ -349,7 +349,7 @@ jobs:
|
|||
run: ci/print-test-failures.sh
|
||||
- name: Upload failed tests' directories
|
||||
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: failed-tests-${{matrix.vector.jobname}}
|
||||
path: ${{env.FAILED_TEST_ARTIFACTS}}
|
||||
|
|
@ -362,7 +362,7 @@ jobs:
|
|||
CI_JOB_IMAGE: ubuntu-latest
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- run: ci/install-dependencies.sh
|
||||
- run: ci/run-build-and-minimal-fuzzers.sh
|
||||
dockerized:
|
||||
|
|
@ -439,7 +439,7 @@ jobs:
|
|||
else
|
||||
apt-get -q update && apt-get -q -y install git
|
||||
fi
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- run: ci/install-dependencies.sh
|
||||
- run: useradd builder --create-home
|
||||
- run: chown -R builder .
|
||||
|
|
@ -449,7 +449,7 @@ jobs:
|
|||
run: sudo --preserve-env --set-home --user=builder ci/print-test-failures.sh
|
||||
- name: Upload failed tests' directories
|
||||
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: failed-tests-${{matrix.vector.jobname}}
|
||||
path: ${{env.FAILED_TEST_ARTIFACTS}}
|
||||
|
|
@ -464,7 +464,7 @@ jobs:
|
|||
group: static-analysis-${{ github.ref }}
|
||||
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- run: ci/install-dependencies.sh
|
||||
- run: ci/run-static-analysis.sh
|
||||
- run: ci/check-directional-formatting.bash
|
||||
|
|
@ -480,7 +480,7 @@ jobs:
|
|||
group: rust-analysis-${{ github.ref }}
|
||||
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- run: ci/install-dependencies.sh
|
||||
- run: ci/run-rust-checks.sh
|
||||
sparse:
|
||||
|
|
@ -494,7 +494,7 @@ jobs:
|
|||
group: sparse-${{ github.ref }}
|
||||
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install other dependencies
|
||||
run: ci/install-dependencies.sh
|
||||
- run: make sparse
|
||||
|
|
@ -510,6 +510,6 @@ jobs:
|
|||
CI_JOB_IMAGE: ubuntu-latest
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- run: ci/install-dependencies.sh
|
||||
- run: ci/test-documentation.sh
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@
|
|||
/git-for-each-ref
|
||||
/git-for-each-repo
|
||||
/git-format-patch
|
||||
/git-format-rev
|
||||
/git-fsck
|
||||
/git-fsck-objects
|
||||
/git-fsmonitor--daemon
|
||||
|
|
@ -182,6 +183,7 @@
|
|||
/git-update-server-info
|
||||
/git-upload-archive
|
||||
/git-upload-pack
|
||||
/git-url-parse
|
||||
/git-var
|
||||
/git-verify-commit
|
||||
/git-verify-pack
|
||||
|
|
|
|||
|
|
@ -216,6 +216,30 @@ would be significant, we may decide to defer this change to a subsequent minor
|
|||
release. This evaluation will also take into account our own experience with
|
||||
how painful it is to keep Rust an optional component.
|
||||
|
||||
* The default value of `safe.bareRepository` will change from `all` to
|
||||
`explicit`. It is all too easy for an attacker to trick a user into cloning a
|
||||
repository that contains an embedded bare repository with malicious hooks
|
||||
configured. If the user enters that subdirectory and runs any Git command, Git
|
||||
discovers the bare repository and the hooks fire. The user does not even need
|
||||
to run a Git command explicitly: many shell prompts run `git status` in the
|
||||
background to display branch and dirty state information, and `git status` in
|
||||
turn may invoke the fsmonitor hook if so configured, making the user
|
||||
vulnerable the moment they `cd` into the directory. The `safe.bareRepository`
|
||||
configuration variable was introduced in 8959555cee (setup_git_directory():
|
||||
add an owner check for the top-level directory, 2022-03-02) with a default of
|
||||
`all` to preserve backwards compatibility.
|
||||
+
|
||||
Changing the default to `explicit` means that Git will refuse to work with bare
|
||||
repositories that are discovered implicitly by walking up the directory tree.
|
||||
Bare repositories specified explicitly via the `--git-dir` command-line option
|
||||
or the `GIT_DIR` environment variable continue to work regardless of this
|
||||
setting. Repositories that look like a `.git` directory, a worktree, or a
|
||||
submodule directory are also unaffected.
|
||||
+
|
||||
Users who rely on implicit discovery of bare repositories can restore the
|
||||
previous behavior by setting `safe.bareRepository=all` in their global or
|
||||
system configuration.
|
||||
|
||||
=== Removals
|
||||
|
||||
* Support for grafting commits has long been superseded by git-replace(1).
|
||||
|
|
|
|||
|
|
@ -693,6 +693,12 @@ For C programs:
|
|||
char *dogs[] = ...;
|
||||
walk_all_dogs(dogs);
|
||||
|
||||
- For file timestamps, do not use "st_mtim" (and other timestamp
|
||||
members in "struct stat") unconditionally; not everybody is POSIX
|
||||
(grep for USE_ST_TIMESPEC). If you only need a timestamp in whole
|
||||
second resolution, "st_mtime" should work fine everywhere.
|
||||
|
||||
|
||||
For Perl programs:
|
||||
|
||||
- Most of the C guidelines above apply.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
Git v2.54.1 Release Notes
|
||||
=========================
|
||||
|
||||
This release is primarily to merge fixes accumulated on the 'master'
|
||||
front to prepare for 2.55 release that are still relevant to 2.54.x
|
||||
maintenance track.
|
||||
|
||||
Fixes since v2.54
|
||||
-----------------
|
||||
|
||||
* Headers from glibc 2.43 when used with clang does not allow
|
||||
disabling C11 language features, causing build failures..
|
||||
|
||||
* Revert a recent change that introduced a regression to help mksh users.
|
||||
|
||||
* Update various GitHub Actions versions.
|
||||
|
||||
* Avoid hitting the pathname limit for socks proxy socket during the
|
||||
test.
|
||||
|
||||
* To help Windows 10 installations, avoid removing files whose
|
||||
contents are still mmap()'ed.
|
||||
|
||||
* Stop using unmaintained custom allocator in Windows build which was
|
||||
the last user of the code.
|
||||
|
||||
* Further update to the i18n alias support to avoid regressions.
|
||||
|
||||
Also contains minor documentation updates and code clean-ups.
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
Git v2.55 Release Notes
|
||||
=======================
|
||||
|
||||
UI, Workflows & Features
|
||||
------------------------
|
||||
|
||||
* Hook scripts defined via the configuration system can now be
|
||||
configured to run in parallel.
|
||||
|
||||
* The userdiff driver for the Scheme language has been extended to
|
||||
cover other Lisp dialects.
|
||||
|
||||
* Terminal control sequences coming over the sideband while talking
|
||||
to a remote repository are mostly disabled by default, except for
|
||||
ANSI color escape sequences.
|
||||
|
||||
* "ort" merge backend improvements.
|
||||
|
||||
* "git checkout -m another-branch" was invented to deal with local
|
||||
changes to paths that are different between the current and the new
|
||||
branch, but it gave only one chance to resolve conflicts. The command
|
||||
was taught to create a stash to save the local changes.
|
||||
|
||||
* A new builtin "git format-rev" is introduced for pretty formatting
|
||||
one revision expression per line or commit object names found in
|
||||
running text.
|
||||
|
||||
* "git history" learned "fixup" command.
|
||||
|
||||
* The internal URL parsing logic has been made accessible via a new
|
||||
subcommand "git url-parse".
|
||||
|
||||
* Misspelt proxy URL (e.g., httt://...) did not trigger any warning
|
||||
or failure, which has been corrected.
|
||||
|
||||
* Document the fact that .git/info/exclude is shared across worktrees
|
||||
linked to the same repository.
|
||||
|
||||
* The command line parser for "git diff" learned a few options take
|
||||
only non-negative integers.
|
||||
|
||||
|
||||
Performance, Internal Implementation, Development Support etc.
|
||||
--------------------------------------------------------------
|
||||
|
||||
* Promisor remote handling has been refactored and fixed in
|
||||
preparation for auto-configuration of advertised remotes.
|
||||
|
||||
* Rust support is enabled by default (but still allows opting out) in
|
||||
some future version of Git.
|
||||
|
||||
* Preparation of the xdiff/ codebase to work with Rust.
|
||||
|
||||
* Use a larger buffer size in the code paths to ingest pack stream.
|
||||
|
||||
* Refactor service routines in the ref subsystem backends.
|
||||
|
||||
* Shrink wasted memory in Myers diff that does not account for common
|
||||
prefix and suffix removal.
|
||||
|
||||
* Enable expensive tests to catch topics that may cause breakages on
|
||||
integration branches closer to their origin in the contributor PR
|
||||
builds.
|
||||
|
||||
* "git merge-base" optimization.
|
||||
|
||||
* The limit_list() function that is one of the core part of the
|
||||
revision traversal infrastructure has been optimized by replacing
|
||||
its use of linear list with priority queue.
|
||||
|
||||
* In a lazy clone, "git cherry" and "git grep" often fetch necessary
|
||||
blob objects one by one from promisor remotes. It has been corrected
|
||||
to collect necessary object names and fetch them in bulk to gain
|
||||
reasonable performance.
|
||||
|
||||
* The logic to determine that branches in an octopus merge are
|
||||
independent has been optimized.
|
||||
|
||||
* The consistency checks for the files reference backend have been updated
|
||||
to skip lock files earlier, avoiding unnecessary parsing of
|
||||
intermediate files.
|
||||
|
||||
* The negotiation tip options in "git fetch" have been reworked to
|
||||
allow requiring certain refs to be sent as "have" lines, and to
|
||||
restrict negotiation to a specific set of refs.
|
||||
|
||||
* The repacking code has been refactored and compaction of MIDX layers
|
||||
have been implemented, and incremental strategy that does not require
|
||||
all-into-one repacking has been introduced.
|
||||
|
||||
* ODB transaction interface is being reworked to explicitly handle
|
||||
object writes.
|
||||
|
||||
* Add a new odb "in-memory" source that is meant to only hold
|
||||
tentative objects (like the virtual blob object that represents the
|
||||
working tree file used by "git blame").
|
||||
|
||||
* Many uses of the_repository has been updated to use a more
|
||||
appropriate struct repository instance in setup.c codepath.
|
||||
|
||||
|
||||
Fixes since v2.54
|
||||
-----------------
|
||||
|
||||
* Code clean-up to use the right instance of a repository instance in
|
||||
calls inside refs subsystem.
|
||||
(merge 57c590feb9 sp/refs-reduce-the-repository later to maint).
|
||||
|
||||
* The check that implements the logic to see if an in-core cache-tree
|
||||
is fully ready to write out a tree object was broken, which has
|
||||
been corrected.
|
||||
(merge 521731213c dl/cache-tree-fully-valid-fix later to maint).
|
||||
|
||||
* The test suite harness and many individual test scripts have been
|
||||
updated to work correctly when 'set -e' is in effect, which helps
|
||||
detect misspelled test commands.
|
||||
(merge ffe8005b9d ps/test-set-e-clean later to maint).
|
||||
|
||||
* Revert a recent change that introduced a regression to help mksh users.
|
||||
|
||||
* Update various GitHub Actions versions.
|
||||
|
||||
* Avoid hitting the pathname limit for socks proxy socket during the
|
||||
test..
|
||||
|
||||
* To help Windows 10 installations, avoid removing files whose
|
||||
contents are still mmap()'ed.
|
||||
|
||||
* The 'git backfill' command now rejects revision-limiting options that
|
||||
are incompatible with its operation, uses standard documentation for
|
||||
revision ranges, and includes blobs from boundary commits by default
|
||||
to improve performance of subsequent operations.
|
||||
(merge a1ad4a0fca en/backfill-fixes-and-edges later to maint).
|
||||
|
||||
* "git grep" update.
|
||||
(merge 9ff4b5ab1b rs/grep-column-only-match-fix later to maint).
|
||||
|
||||
* Headers from glibc 2.43 when used with clang does not allow
|
||||
disabling C11 language features, causing build failures..
|
||||
|
||||
* The 'http.emptyAuth=auto' configuration now correctly attempts
|
||||
Negotiate authentication before falling back to manual credentials.
|
||||
This allows seamless Kerberos ticket-based authentication without
|
||||
requiring users to explicitly set 'http.emptyAuth=true'.
|
||||
(merge 4919938d28 mc/http-emptyauth-negotiate-fix later to maint).
|
||||
|
||||
* Ramifications of turning off commit-graph has been documented a bit
|
||||
more clearly.
|
||||
(merge 48c855bb8f kh/doc-commit-graph later to maint).
|
||||
|
||||
* "git rebase --update-refs", when used with an rebase.instructionFormat
|
||||
with "%d" (describe) in it, tried to update local branch HEAD by
|
||||
mistake, which has been corrected.
|
||||
(merge 106b6885c7 ag/rebase-update-refs-limit-to-branches later to maint).
|
||||
|
||||
* Tweak the way how sideband messages from remote are printed while
|
||||
we talk with a remote repository to avoid tickling terminal
|
||||
emulator glitches.
|
||||
(merge 31e8fcabd8 rs/sideband-clear-line-before-print later to maint).
|
||||
|
||||
* The configuration variable submodule.fetchJobs was not read correctly,
|
||||
which has been corrected.
|
||||
(merge aa45a5902f sj/submodule-update-clone-config-fix later to maint).
|
||||
|
||||
* Update code paths that assumed "unsigned long" was long enough for
|
||||
"size_t".
|
||||
(merge 7a094d68a2 js/objects-larger-than-4gb-on-windows later to maint).
|
||||
|
||||
* Stop using unmaintained custom allocator in Windows build which was
|
||||
the last user of the code.
|
||||
|
||||
* The computation to shorten the filenames shown in diffstat measured
|
||||
width of individual UTF-8 characters to add up, but forgot to take
|
||||
into account error cases (e.g., an invalid UTF-8 sequence, or a
|
||||
control character).
|
||||
(merge 09d86a3b98 en/diffstat-utf8-truncation-fix later to maint).
|
||||
|
||||
* Some tests assume that bare repository accesses are by default
|
||||
allowed; rewrite some of them to avoid the assumption, rewrite
|
||||
others to explicitly set safe.bareRepository to allow them.
|
||||
(merge 985b38ca6c js/adjust-tests-to-explicitly-access-bare-repo later to maint).
|
||||
|
||||
* Signing commit with custom encoding was passing the data to be
|
||||
signed at a wrong stage in the pipeline, which has been corrected.
|
||||
(merge 7735d7eee3 bc/sign-commit-with-custom-encoding later to maint).
|
||||
|
||||
* Further update to the i18n alias support to avoid regressions.
|
||||
|
||||
* "git fetch --deepen=<n>" in a full clone truncated the history to <n>
|
||||
commits deep, which has been corrected to be a no-op instead.
|
||||
(merge 2431f5e0e5 sp/shallow-deepen-on-non-shallow-repo-fix later to maint).
|
||||
|
||||
* "git maintenance" that goes background did not use the lockfile to
|
||||
prevent multiple maintenance processes from running at the same
|
||||
time, which has been corrected.
|
||||
(merge 29364f1624 ps/maintenance-daemonize-lockfix later to maint).
|
||||
|
||||
* Remove ineffective strbuf presizing that would have computed an
|
||||
allocation that would not have fit in the available memory anyway,
|
||||
or too small due to integer wraparound to cause immediate automatic
|
||||
growing.
|
||||
(merge a9ce8526dc jk/pretty-no-strbuf-presizing later to maint).
|
||||
|
||||
* The HTTP walker misinterpreted the alternates file that gives an
|
||||
absolute path when the server URL does not have the final slash
|
||||
(i.e., "https://example.com" not "https://example.com/").
|
||||
(merge b92387cd55 jk/dumb-http-alternate-fix later to maint).
|
||||
|
||||
* Other code cleanup, docfix, build fix, etc.
|
||||
(merge 80f4b802e9 ja/doc-difftool-synopsis-style later to maint).
|
||||
(merge b96490241e jc/doc-timestamps-in-stat later to maint).
|
||||
(merge ef85286e51 ss/t7004-unhide-git-failures later to maint).
|
||||
(merge 7584d10bc2 mf/format-patch-cover-letter-format-docfix later to maint).
|
||||
(merge 8547908eb3 pw/rename-to-get-current-worktree later to maint).
|
||||
(merge 890229b3f3 sg/t6112-unwanted-tilde-expansion-fix later to maint).
|
||||
(merge ab9753e7bc kh/doc-restore-double-underscores-fix later to maint).
|
||||
(merge 4a9e097228 za/t2000-modernise-more later to maint).
|
||||
(merge b635fd0725 kh/doc-log-decorate-list later to maint).
|
||||
(merge 65ea197dca jk/commit-sign-overflow-fix later to maint).
|
||||
(merge 3ccb16052a jk/apply-leakfix later to maint).
|
||||
(merge 5e6e8dc786 tb/pseudo-merge-bugfixes later to maint).
|
||||
(merge 6d09e798bc pb/doc-diff-format-updates later to maint).
|
||||
(merge 34a891a2d3 rs/trailer-fold-optim later to maint).
|
||||
(merge 499f9048e0 ps/t3903-cover-stash-include-untracked later to maint).
|
||||
(merge b56ab270aa jk/sq-dequote-cleanup later to maint).
|
||||
(merge 29d9fdcf10 rs/use-builtin-add-overflow-explicitly-on-clang later to maint).
|
||||
|
|
@ -523,6 +523,8 @@ include::config/sequencer.adoc[]
|
|||
|
||||
include::config/showbranch.adoc[]
|
||||
|
||||
include::config/sideband.adoc[]
|
||||
|
||||
include::config/sparse.adoc[]
|
||||
|
||||
include::config/splitindex.adoc[]
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ will be updated more often than a reference pointing at an old commit.
|
|||
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 `1`
|
||||
(inclusive). The default is `1`.
|
||||
unstable pseudo-merge bitmap. Must be greater than `0` and
|
||||
less than or equal to `1`. The default is `1`.
|
||||
|
||||
bitmapPseudoMerge.<name>.threshold::
|
||||
Determines the minimum age of non-bitmapped commits (among
|
||||
|
|
|
|||
|
|
@ -1,43 +1,43 @@
|
|||
diff.tool::
|
||||
`diff.tool`::
|
||||
Controls which diff tool is used by linkgit:git-difftool[1].
|
||||
This variable overrides the value configured in `merge.tool`.
|
||||
The list below shows the valid built-in values.
|
||||
Any other value is treated as a custom diff tool and requires
|
||||
that a corresponding difftool.<tool>.cmd variable is defined.
|
||||
that a corresponding `difftool.<tool>.cmd` variable is defined.
|
||||
|
||||
diff.guitool::
|
||||
`diff.guitool`::
|
||||
Controls which diff tool is used by linkgit:git-difftool[1] when
|
||||
the -g/--gui flag is specified. This variable overrides the value
|
||||
the `-g`/`--gui` flag is specified. This variable overrides the value
|
||||
configured in `merge.guitool`. The list below shows the valid
|
||||
built-in values. Any other value is treated as a custom diff tool
|
||||
and requires that a corresponding difftool.<guitool>.cmd variable
|
||||
and requires that a corresponding `difftool.<guitool>.cmd` variable
|
||||
is defined.
|
||||
|
||||
include::{build_dir}/mergetools-diff.adoc[]
|
||||
|
||||
difftool.<tool>.cmd::
|
||||
`difftool.<tool>.cmd`::
|
||||
Specify the command to invoke the specified diff tool.
|
||||
The specified command is evaluated in shell with the following
|
||||
variables available: 'LOCAL' is set to the name of the temporary
|
||||
file containing the contents of the diff pre-image and 'REMOTE'
|
||||
variables available: `LOCAL` is set to the name of the temporary
|
||||
file containing the contents of the diff pre-image and `REMOTE`
|
||||
is set to the name of the temporary file containing the contents
|
||||
of the diff post-image.
|
||||
+
|
||||
See the `--tool=<tool>` option in linkgit:git-difftool[1] for more details.
|
||||
|
||||
difftool.<tool>.path::
|
||||
`difftool.<tool>.path`::
|
||||
Override the path for the given tool. This is useful in case
|
||||
your tool is not in the PATH.
|
||||
|
||||
difftool.trustExitCode::
|
||||
`difftool.trustExitCode`::
|
||||
Exit difftool if the invoked diff tool returns a non-zero exit status.
|
||||
+
|
||||
See the `--trust-exit-code` option in linkgit:git-difftool[1] for more details.
|
||||
|
||||
difftool.prompt::
|
||||
`difftool.prompt`::
|
||||
Prompt before each invocation of the diff tool.
|
||||
|
||||
difftool.guiDefault::
|
||||
`difftool.guiDefault`::
|
||||
Set `true` to use the `diff.guitool` by default (equivalent to specifying
|
||||
the `--gui` argument), or `auto` to select `diff.guitool` or `diff.tool`
|
||||
depending on the presence of a `DISPLAY` environment variable value. The
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@
|
|||
default is `skipping`. Unknown values will cause `git fetch` to
|
||||
error out.
|
||||
+
|
||||
See also the `--negotiate-only` and `--negotiation-tip` options to
|
||||
See also the `--negotiate-only` and `--negotiation-restrict` options to
|
||||
linkgit:git-fetch[1].
|
||||
|
||||
`fetch.showForcedUpdates`::
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ format.coverLetter::
|
|||
Default is false.
|
||||
|
||||
format.commitListFormat::
|
||||
When the `--cover-letter-format` option is not given, `format-patch`
|
||||
When the `--commit-list-format` option is not given, `format-patch`
|
||||
uses the value of this variable to decide how to format the entry of
|
||||
each commit. Defaults to `shortlog`.
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,12 @@ hook.<friendly-name>.event::
|
|||
events, specify the key more than once. An empty value resets
|
||||
the list of events, clearing any previously defined events for
|
||||
`hook.<friendly-name>`. See linkgit:git-hook[1].
|
||||
+
|
||||
The `<friendly-name>` must not be the same as a known hook event name
|
||||
(e.g. do not use `hook.pre-commit.event`). Using a known event name as
|
||||
a friendly-name is a fatal error because it creates an ambiguity with
|
||||
`hook.<event>.enabled` and `hook.<event>.jobs`. For unknown event names,
|
||||
a warning is issued when `<friendly-name>` matches the event value.
|
||||
|
||||
hook.<friendly-name>.enabled::
|
||||
Whether the hook `hook.<friendly-name>` is enabled. Defaults to `true`.
|
||||
|
|
@ -22,3 +28,73 @@ hook.<friendly-name>.enabled::
|
|||
configuration. This is particularly useful when a hook is defined
|
||||
in a system or global config file and needs to be disabled for a
|
||||
specific repository. See linkgit:git-hook[1].
|
||||
|
||||
hook.<friendly-name>.parallel::
|
||||
Whether the hook `hook.<friendly-name>` may run in parallel with other hooks
|
||||
for the same event. Defaults to `false`. Set to `true` only when the
|
||||
hook script is safe to run concurrently with other hooks for the same
|
||||
event. If any hook for an event does not have this set to `true`,
|
||||
all hooks for that event run sequentially regardless of `hook.jobs`.
|
||||
Only configured (named) hooks need to declare this. Traditional hooks
|
||||
found in the hooks directory do not need to, and run in parallel when
|
||||
the effective job count is greater than 1. See linkgit:git-hook[1].
|
||||
|
||||
hook.<event>.enabled::
|
||||
Switch to enable or disable all hooks for the `<event>` hook event.
|
||||
When set to `false`, no hooks fire for that event, regardless of any
|
||||
per-hook `hook.<friendly-name>.enabled` settings. Defaults to `true`.
|
||||
See linkgit:git-hook[1].
|
||||
+
|
||||
Note on naming: `<event>` must be the event name (e.g. `pre-commit`),
|
||||
not a hook friendly-name. Since using a known event name as a
|
||||
friendly-name is disallowed (see `hook.<friendly-name>.event` above),
|
||||
there is no ambiguity between event-level and per-hook `.enabled`
|
||||
settings for known events. For unknown events, if a friendly-name
|
||||
matches the event name despite the warning, `.enabled` is treated
|
||||
as per-hook only.
|
||||
|
||||
hook.<event>.jobs::
|
||||
Specifies how many hooks can be run simultaneously for the `<event>`
|
||||
hook event (e.g. `hook.post-receive.jobs = 4`). Overrides `hook.jobs`
|
||||
for this specific event. The same parallelism restrictions apply: this
|
||||
setting has no effect unless all configured hooks for the event have
|
||||
`hook.<friendly-name>.parallel` set to `true`. Set to `-1` to use the
|
||||
number of available CPU cores. Must be a positive integer or `-1`;
|
||||
zero is rejected with a warning. See linkgit:git-hook[1].
|
||||
+
|
||||
Note on naming: although this key resembles `hook.<friendly-name>.*`
|
||||
(a per-hook setting), `<event>` must be the event name, not a hook
|
||||
friendly name. The key component is stored literally and looked up by
|
||||
event name at runtime with no translation between the two namespaces.
|
||||
A key like `hook.my-hook.jobs` is stored under `"my-hook"` but the
|
||||
lookup at runtime uses the event name (e.g. `"post-receive"`), so
|
||||
`hook.my-hook.jobs` is silently ignored even when `my-hook` is
|
||||
registered for that event. Use `hook.post-receive.jobs` or any other
|
||||
valid event name when setting `hook.<event>.jobs`.
|
||||
|
||||
hook.jobs::
|
||||
Specifies how many hooks can be run simultaneously during parallelized
|
||||
hook execution. If unspecified, defaults to 1 (serial execution).
|
||||
Set to `-1` to use the number of available CPU cores.
|
||||
Can be overridden on a per-event basis with `hook.<event>.jobs`.
|
||||
Some hooks always run sequentially regardless of this setting because
|
||||
they operate on shared data and cannot safely be parallelized:
|
||||
+
|
||||
--
|
||||
`applypatch-msg`;;
|
||||
`prepare-commit-msg`;;
|
||||
`commit-msg`;;
|
||||
Receive a commit message file and may rewrite it in place.
|
||||
`pre-commit`;;
|
||||
`post-checkout`;;
|
||||
`push-to-checkout`;;
|
||||
`post-commit`;;
|
||||
Access the working tree, index, or repository state.
|
||||
--
|
||||
+
|
||||
This setting has no effect unless all configured hooks for the event have
|
||||
`hook.<friendly-name>.parallel` set to `true`.
|
||||
+
|
||||
For `pre-push` hooks, which normally keep stdout and stderr separate,
|
||||
setting this to a value greater than 1 (or passing `-j`) will merge stdout
|
||||
into stderr to allow correct de-interleaving of parallel output.
|
||||
|
|
|
|||
|
|
@ -59,7 +59,18 @@ http.emptyAuth::
|
|||
Attempt authentication without seeking a username or password. This
|
||||
can be used to attempt GSS-Negotiate authentication without specifying
|
||||
a username in the URL, as libcurl normally requires a username for
|
||||
authentication.
|
||||
authentication. Possible values are:
|
||||
+
|
||||
--
|
||||
* `auto` (default) - Send empty credentials only if the server's 401 response
|
||||
advertises an authentication mechanism that requires them (such as
|
||||
GSS-Negotiate); otherwise fall back to prompting via the credential helper.
|
||||
* `true` - Always send empty credentials on the very first request, before
|
||||
receiving any 401 response from the server.
|
||||
* `false` - Never send empty credentials. Mechanisms that require
|
||||
empty credentials or an explicit username, such as GSS-Negotiate, will not
|
||||
work.
|
||||
--
|
||||
|
||||
http.proactiveAuth::
|
||||
Attempt authentication without first making an unauthenticated attempt and
|
||||
|
|
|
|||
|
|
@ -52,13 +52,13 @@
|
|||
if `merge.tool` is configured as _<variant>_), Git will consult
|
||||
`mergetool.<variant>.layout` to determine the tool's layout. If the
|
||||
variant-specific configuration is not available, `vimdiff` ' s is used as
|
||||
fallback. If that too is not available, a default layout with 4 windows
|
||||
will be used. To configure the layout, see the 'BACKEND SPECIFIC HINTS'
|
||||
fallback. If that too is not available, a default layout with 4 windows
|
||||
will be used.
|
||||
ifdef::git-mergetool[]
|
||||
section.
|
||||
To configure the layout, see the 'BACKEND SPECIFIC HINTS' section.
|
||||
endif::[]
|
||||
ifndef::git-mergetool[]
|
||||
section in linkgit:git-mergetool[1].
|
||||
To configure the layout, see the 'BACKEND SPECIFIC HINTS' section in linkgit:git-mergetool[1].
|
||||
endif::[]
|
||||
|
||||
`mergetool.hideResolved`::
|
||||
|
|
|
|||
|
|
@ -107,6 +107,55 @@ priority configuration file (e.g. `.git/config` in a repository) to clear
|
|||
the values inherited from a lower priority configuration files (e.g.
|
||||
`$HOME/.gitconfig`).
|
||||
|
||||
remote.<name>.negotiationRestrict::
|
||||
When negotiating with this remote during `git fetch`, restrict the
|
||||
commits advertised as "have" lines to only those reachable from refs
|
||||
matching the given patterns. This multi-valued config option behaves
|
||||
like `--negotiation-restrict` on the command line.
|
||||
+
|
||||
Each value is either an exact ref name (e.g. `refs/heads/release`) or a
|
||||
glob pattern (e.g. `refs/heads/release/*`). The pattern syntax is the
|
||||
same as for `--negotiation-restrict`.
|
||||
+
|
||||
These config values are used as defaults for the `--negotiation-restrict`
|
||||
command-line option. If `--negotiation-restrict` (or its synonym
|
||||
`--negotiation-tip`) is specified on the command line, then the config
|
||||
values are not used.
|
||||
+
|
||||
These values also influence negotiation during `git push` if
|
||||
`push.negotiate` is enabled.
|
||||
+
|
||||
Blank values signal to ignore all previous values, allowing a reset of
|
||||
the list from broader config scenarios.
|
||||
|
||||
remote.<name>.negotiationInclude::
|
||||
When negotiating with this remote during `git fetch`, the client
|
||||
advertises a list of commits that exist locally. In repos with
|
||||
many references, this list of "haves" can be truncated. Depending
|
||||
on data shape, dropping certain references may be expensive. This
|
||||
multi-valued config option specifies references, commit hashes,
|
||||
or ref pattern globs whose tips should always be sent as "have"
|
||||
commits during fetch negotiation with this remote.
|
||||
+
|
||||
Each value is either an exact ref name (e.g. `refs/heads/release`), a
|
||||
commit hash, or a glob pattern (e.g. `refs/heads/release/*`). The
|
||||
pattern syntax is the same as for `--negotiation-include`.
|
||||
+
|
||||
These config values are used as defaults for the `--negotiation-include`
|
||||
command-line option. If `--negotiation-include` is specified on the
|
||||
command line, then the config values are not used.
|
||||
+
|
||||
This option is additive with the normal negotiation process: the
|
||||
negotiation algorithm still runs and advertises its own selected commits,
|
||||
but the refs matching `remote.<name>.negotiationInclude` are sent
|
||||
unconditionally on top of those heuristically selected commits.
|
||||
+
|
||||
These values also influence negotiation during `git push` if
|
||||
`push.negotiate` is enabled.
|
||||
+
|
||||
Blank values signal to ignore all previous values, allowing a reset of
|
||||
the list from broader config scenarios.
|
||||
|
||||
remote.<name>.followRemoteHEAD::
|
||||
How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD`
|
||||
when fetching using the configured refspecs of a remote.
|
||||
|
|
|
|||
|
|
@ -46,3 +46,21 @@ repack.midxMustContainCruft::
|
|||
`--write-midx`. When false, cruft packs are only included in the MIDX
|
||||
when necessary (e.g., because they might be required to form a
|
||||
reachability closure with MIDX bitmaps). Defaults to true.
|
||||
|
||||
repack.midxSplitFactor::
|
||||
The factor used in the geometric merging condition when
|
||||
compacting incremental MIDX layers during `git repack` when
|
||||
invoked with the `--write-midx=incremental` option.
|
||||
+
|
||||
Adjacent layers are merged when the accumulated object count of the
|
||||
newer layer exceeds `1/<N>` of the object count of the next deeper
|
||||
layer. Must be at least 2. Defaults to 2.
|
||||
|
||||
repack.midxNewLayerThreshold::
|
||||
The minimum number of packs in the tip MIDX layer before those
|
||||
packs are considered as candidates for geometric repacking
|
||||
during `git repack --write-midx=incremental`.
|
||||
+
|
||||
When the tip layer has fewer packs than this threshold, those packs are
|
||||
excluded from the geometric repack entirely, and are thus left
|
||||
unmodified. Must be at least 1. Defaults to 8.
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ safe.bareRepository::
|
|||
Specifies which bare repositories Git will work with. The currently
|
||||
supported values are:
|
||||
+
|
||||
* `all`: Git works with all bare repositories. This is the default.
|
||||
* `all`: Git works with all bare repositories. This is the default in
|
||||
Git 2.x.
|
||||
* `explicit`: Git only works with bare repositories specified via
|
||||
the top-level `--git-dir` command-line option, or the `GIT_DIR`
|
||||
environment variable (see linkgit:git[1]).
|
||||
environment variable (see linkgit:git[1]). This will be the default
|
||||
in Git 3.0.
|
||||
+
|
||||
If you do not use bare repositories in your workflow, then it may be
|
||||
beneficial to set `safe.bareRepository` to `explicit` in your global
|
||||
|
|
@ -13,6 +15,10 @@ config. This will protect you from attacks that involve cloning a
|
|||
repository that contains a bare repository and running a Git command
|
||||
within that directory.
|
||||
+
|
||||
If you use bare repositories regularly and want to preserve the current
|
||||
behavior after upgrading to Git 3.0, set `safe.bareRepository` to `all`
|
||||
in your global or system config.
|
||||
+
|
||||
This config setting is only respected in protected configuration (see
|
||||
<<SCOPES>>). This prevents untrusted repositories from tampering with
|
||||
this value.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
sideband.allowControlCharacters::
|
||||
By default, control characters that are delivered via the sideband
|
||||
are masked, except ANSI color sequences. This prevents potentially
|
||||
unwanted ANSI escape sequences from being sent to the terminal. Use
|
||||
this config setting to override this behavior (the value can be
|
||||
a comma-separated list of the following keywords):
|
||||
+
|
||||
--
|
||||
`color`::
|
||||
Allow ANSI color sequences, line feeds and horizontal tabs,
|
||||
but mask all other control characters. This is the default.
|
||||
`cursor:`:
|
||||
Allow control sequences that move the cursor. This is
|
||||
disabled by default.
|
||||
`erase`::
|
||||
Allow control sequences that erase charactrs. This is
|
||||
disabled by default.
|
||||
`false`::
|
||||
Mask all control characters other than line feeds and
|
||||
horizontal tabs.
|
||||
`true`::
|
||||
Allow all control characters to be sent to the terminal.
|
||||
--
|
||||
|
||||
sideband.<url>.*::
|
||||
Apply the `sideband.*` option selectively to specific URLs. The
|
||||
same URL matching logic applies as for `http.<url>.*` settings.
|
||||
|
|
@ -19,9 +19,9 @@ compared differs:
|
|||
`git-diff-files [<pattern>...]`::
|
||||
compares the index and the files on the filesystem.
|
||||
|
||||
The `git-diff-tree` command begins its output by printing the hash of
|
||||
what is being compared. After that, all the commands print one output
|
||||
line per changed file.
|
||||
All the commands print one output line per changed file,
|
||||
except `git diff-files` in the case of an unmerged file, which prints
|
||||
both an "unmerged" and an "in-place edit" line.
|
||||
|
||||
An output line is formatted this way:
|
||||
|
||||
|
|
@ -37,13 +37,13 @@ unmerged :000000 000000 0000000 0000000 U file6
|
|||
That is, from the left to the right:
|
||||
|
||||
. a colon.
|
||||
. mode for "src"; 000000 if creation or unmerged.
|
||||
. mode for "src"; 000000 if creation, or if "src" is from the index and is unmerged.
|
||||
. a space.
|
||||
. mode for "dst"; 000000 if deletion or unmerged.
|
||||
. mode for "dst"; 000000 if deletion, or if "dst" is from the index and is unmerged.
|
||||
. a space.
|
||||
. sha1 for "src"; 0\{40\} if creation or unmerged.
|
||||
. sha1 for "src"; 0\{40\} if creation, or if "src" is from the index and is unmerged.
|
||||
. a space.
|
||||
. sha1 for "dst"; 0\{40\} if deletion, unmerged or "work tree out of sync with the index".
|
||||
. sha1 for "dst"; 0\{40\} if deletion, if "dst" is from the index and is unmerged, or if "dst" is from the work tree and is out of sync with the index.
|
||||
. a space.
|
||||
. status, followed by optional "score" number.
|
||||
. a tab or a NUL when `-z` option is used.
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ the current repository has the same history as the source repository.
|
|||
`.git/shallow`. This option updates `.git/shallow` and accepts such
|
||||
refs.
|
||||
|
||||
`--negotiation-restrict=(<commit>|<glob>)`::
|
||||
`--negotiation-tip=(<commit>|<glob>)`::
|
||||
By default, Git will report, to the server, commits reachable
|
||||
from all local refs to find common commits in an attempt to
|
||||
|
|
@ -58,6 +59,9 @@ the current repository has the same history as the source repository.
|
|||
local ref is likely to have commits in common with the
|
||||
upstream ref being fetched.
|
||||
+
|
||||
`--negotiation-restrict` is the preferred name for this option;
|
||||
`--negotiation-tip` is accepted as a synonym.
|
||||
+
|
||||
This option may be specified more than once; if so, Git will report
|
||||
commits reachable from any of the given commits.
|
||||
+
|
||||
|
|
@ -69,9 +73,32 @@ See also the `fetch.negotiationAlgorithm` and `push.negotiate`
|
|||
configuration variables documented in linkgit:git-config[1], and the
|
||||
`--negotiate-only` option below.
|
||||
|
||||
`--negotiation-include=(<commit>|<glob>)`::
|
||||
Ensure that the commits at the given tips are always sent as "have"
|
||||
lines during fetch negotiation, regardless of what the negotiation
|
||||
algorithm selects. This is useful to guarantee that common
|
||||
history reachable from specific refs is always considered, even
|
||||
when `--negotiation-restrict` restricts the set of tips or when
|
||||
the negotiation algorithm would otherwise skip them.
|
||||
+
|
||||
This option may be specified more than once; if so, each commit is sent
|
||||
unconditionally.
|
||||
+
|
||||
The argument may be an exact ref name (e.g. `refs/heads/release`), an
|
||||
object hash, or a glob pattern (e.g. `refs/heads/release/{asterisk}`).
|
||||
The pattern syntax is the same as for `--negotiation-restrict`.
|
||||
+
|
||||
If `--negotiation-restrict` is used, the have set is first restricted by
|
||||
that option and then increased to include the tips specified by
|
||||
`--negotiation-include`.
|
||||
+
|
||||
If this option is not specified on the command line, then any
|
||||
`remote.<name>.negotiationInclude` config values for the current remote
|
||||
are used instead.
|
||||
|
||||
`--negotiate-only`::
|
||||
Do not fetch anything from the server, and instead print the
|
||||
ancestors of the provided `--negotiation-tip=` arguments,
|
||||
ancestors of the provided `--negotiation-restrict=` arguments,
|
||||
which we have in common with the server.
|
||||
+
|
||||
This is incompatible with `--recurse-submodules=(yes|on-demand)`.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ git-backfill - Download missing objects in a partial clone
|
|||
SYNOPSIS
|
||||
--------
|
||||
[synopsis]
|
||||
git backfill [--min-batch-size=<n>] [--[no-]sparse]
|
||||
git backfill [--min-batch-size=<n>] [--[no-]sparse] [--[no-]include-edges] [<revision-range>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
|
@ -43,7 +43,7 @@ smaller network calls than downloading the entire repository at clone
|
|||
time.
|
||||
|
||||
By default, `git backfill` downloads all blobs reachable from the `HEAD`
|
||||
commit. This set can be restricted or expanded using various options.
|
||||
commit. This set can be restricted or expanded using various options below.
|
||||
|
||||
THIS COMMAND IS EXPERIMENTAL. ITS BEHAVIOR MAY CHANGE IN THE FUTURE.
|
||||
|
||||
|
|
@ -63,7 +63,23 @@ OPTIONS
|
|||
current sparse-checkout. If the sparse-checkout feature is enabled,
|
||||
then `--sparse` is assumed and can be disabled with `--no-sparse`.
|
||||
|
||||
You may also specify the commit limiting options from linkgit:git-rev-list[1].
|
||||
`--include-edges`::
|
||||
`--no-include-edges`::
|
||||
Include blobs from boundary commits in the backfill. Useful in
|
||||
preparation for commands like `git log -p A..B` or `git replay
|
||||
--onto TARGET A..B`, where A..B normally excludes A but you need
|
||||
the blobs from A as well. `--include-edges` is the default.
|
||||
|
||||
`<revision-range>`::
|
||||
Backfill only blobs reachable from commits in the specified
|
||||
revision range. When no _<revision-range>_ is specified, it
|
||||
defaults to `HEAD` (i.e. the whole history leading to the
|
||||
current commit). For a complete list of ways to spell
|
||||
_<revision-range>_, see the "Specifying Ranges" section of
|
||||
linkgit:gitrevisions[7].
|
||||
+
|
||||
You may also use commit-limiting options understood by
|
||||
linkgit:git-rev-list[1] such as `--first-parent`, `--since`, or pathspecs.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
|
|
|||
|
|
@ -251,20 +251,19 @@ working tree, by copying them from elsewhere, extracting a tarball, etc.
|
|||
are different between the current branch and the branch to
|
||||
which you are switching, the command refuses to switch
|
||||
branches in order to preserve your modifications in context.
|
||||
However, with this option, a three-way merge between the current
|
||||
branch, your working tree contents, and the new branch
|
||||
is done, and you will be on the new branch.
|
||||
+
|
||||
When a merge conflict happens, the index entries for conflicting
|
||||
paths are left unmerged, and you need to resolve the conflicts
|
||||
and mark the resolved paths with `git add` (or `git rm` if the merge
|
||||
should result in deletion of the path).
|
||||
With this option, the conflicting local changes are
|
||||
automatically stashed before the switch and reapplied
|
||||
afterwards. If the local changes do not overlap with the
|
||||
differences between branches, the switch proceeds without
|
||||
stashing. If reapplying the stash results in conflicts, the
|
||||
entry is saved to the stash list. Resolve the conflicts
|
||||
and run `git stash drop` when done, or clear the working
|
||||
tree (e.g. with `git reset --hard`) before running `git stash
|
||||
pop` later to re-apply your changes.
|
||||
+
|
||||
When checking out paths from the index, this option lets you recreate
|
||||
the conflicted merge in the specified paths. This option cannot be
|
||||
used when checking out paths from a tree-ish.
|
||||
+
|
||||
When switching branches with `--merge`, staged changes may be lost.
|
||||
|
||||
`--conflict=<style>`::
|
||||
The same as `--merge` option above, but changes the way the
|
||||
|
|
@ -578,38 +577,36 @@ $ git checkout mytopic
|
|||
error: You have local changes to 'frotz'; not switching branches.
|
||||
------------
|
||||
|
||||
You can give the `-m` flag to the command, which would try a
|
||||
three-way merge:
|
||||
You can give the `-m` flag to the command, which will carry your local
|
||||
changes to the new branch:
|
||||
|
||||
------------
|
||||
$ git checkout -m mytopic
|
||||
Auto-merging frotz
|
||||
Applied autostash.
|
||||
Switched to branch 'mytopic'
|
||||
The following paths have local changes:
|
||||
M frotz
|
||||
------------
|
||||
|
||||
After this three-way merge, the local modifications are _not_
|
||||
After the switch, the local modifications are reapplied and are _not_
|
||||
registered in your index file, so `git diff` would show you what
|
||||
changes you made since the tip of the new branch.
|
||||
|
||||
=== 3. Merge conflict
|
||||
|
||||
When a merge conflict happens during switching branches with
|
||||
the `-m` option, you would see something like this:
|
||||
When the `--merge` (`-m`) option is given and the local changes
|
||||
overlap with the changes in the branch we're switching to, the
|
||||
changes are stashed and reapplied after the switch. If this
|
||||
process results in conflicts, the stash entry is saved and a
|
||||
message is printed:
|
||||
|
||||
------------
|
||||
$ git checkout -m mytopic
|
||||
Auto-merging frotz
|
||||
ERROR: Merge conflict in frotz
|
||||
fatal: merge program failed
|
||||
------------
|
||||
|
||||
At this point, `git diff` shows the changes cleanly merged as in
|
||||
the previous example, as well as the changes in the conflicted
|
||||
files. Edit and resolve the conflict and mark it resolved with
|
||||
`git add` as usual:
|
||||
|
||||
------------
|
||||
$ edit frotz
|
||||
$ git add frotz
|
||||
Your local changes are stashed, however applying them
|
||||
resulted in conflicts. You can either resolve the conflicts
|
||||
and then discard the stash with "git stash drop", or, if you
|
||||
do not want to resolve them now, run "git reset --hard" and
|
||||
apply the local changes later by running "git stash pop".
|
||||
------------
|
||||
|
||||
CONFIGURATION
|
||||
|
|
|
|||
|
|
@ -146,6 +146,12 @@ $ git show-ref -s | git commit-graph write --stdin-commits
|
|||
$ git rev-parse HEAD | git commit-graph write --stdin-commits --append
|
||||
------------------------------------------------
|
||||
|
||||
CAVEATS
|
||||
-------
|
||||
|
||||
The existence of replace objects or commit grafts turns off reading or
|
||||
writing to the commit-graph. See linkgit:git-replace[1].
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ git-describe - Give an object a human readable name based on an available ref
|
|||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git describe' [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]
|
||||
'git describe' [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]
|
||||
'git describe' <blob>
|
||||
[synopsis]
|
||||
git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]
|
||||
git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]
|
||||
git describe <blob>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
|
@ -22,70 +22,70 @@ abbreviated object name of the most recent commit. The result
|
|||
is a "human-readable" object name which can also be used to
|
||||
identify the commit to other git commands.
|
||||
|
||||
By default (without --all or --tags) `git describe` only shows
|
||||
By default (without `--all` or `--tags`) `git describe` only shows
|
||||
annotated tags. For more information about creating annotated tags
|
||||
see the -a and -s options to linkgit:git-tag[1].
|
||||
see the `-a` and `-s` options to linkgit:git-tag[1].
|
||||
|
||||
If the given object refers to a blob, it will be described
|
||||
as `<commit-ish>:<path>`, such that the blob can be found
|
||||
at `<path>` in the `<commit-ish>`, which itself describes the
|
||||
at _<path>_ in the _<commit-ish>_, which itself describes the
|
||||
first commit in which this blob occurs in a reverse revision walk
|
||||
from HEAD.
|
||||
from `HEAD`.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
<commit-ish>...::
|
||||
Commit-ish object names to describe. Defaults to HEAD if omitted.
|
||||
`<commit-ish>...`::
|
||||
Commit-ish object names to describe. Defaults to `HEAD` if omitted.
|
||||
|
||||
--dirty[=<mark>]::
|
||||
--broken[=<mark>]::
|
||||
`--dirty[=<mark>]`::
|
||||
`--broken[=<mark>]`::
|
||||
Describe the state of the working tree. When the working
|
||||
tree matches HEAD, the output is the same as "git describe
|
||||
HEAD". If the working tree has local modification "-dirty"
|
||||
tree matches `HEAD`, the output is the same as `git describe HEAD`.
|
||||
If the working tree has local modification, `-dirty`
|
||||
is appended to it. If a repository is corrupt and Git
|
||||
cannot determine if there is local modification, Git will
|
||||
error out, unless `--broken' is given, which appends
|
||||
the suffix "-broken" instead.
|
||||
error out, unless `--broken` is given, which appends
|
||||
the suffix `-broken` instead.
|
||||
|
||||
--all::
|
||||
`--all`::
|
||||
Instead of using only the annotated tags, use any ref
|
||||
found in `refs/` namespace. This option enables matching
|
||||
any known branch, remote-tracking branch, or lightweight tag.
|
||||
|
||||
--tags::
|
||||
`--tags`::
|
||||
Instead of using only the annotated tags, use any tag
|
||||
found in `refs/tags` namespace. This option enables matching
|
||||
a lightweight (non-annotated) tag.
|
||||
|
||||
--contains::
|
||||
`--contains`::
|
||||
Instead of finding the tag that predates the commit, find
|
||||
the tag that comes after the commit, and thus contains it.
|
||||
Automatically implies --tags.
|
||||
Automatically implies `--tags`.
|
||||
|
||||
--abbrev=<n>::
|
||||
`--abbrev=<n>`::
|
||||
Instead of using the default number of hexadecimal digits (which
|
||||
will vary according to the number of objects in the repository with
|
||||
a default of 7) of the abbreviated object name, use <n> digits, or
|
||||
as many digits as needed to form a unique object name. An <n> of 0
|
||||
a default of 7) of the abbreviated object name, use _<n>_ digits, or
|
||||
as many digits as needed to form a unique object name. An _<n>_ of 0
|
||||
will suppress long format, only showing the closest tag.
|
||||
|
||||
--candidates=<n>::
|
||||
`--candidates=<n>`::
|
||||
Instead of considering only the 10 most recent tags as
|
||||
candidates to describe the input commit-ish consider
|
||||
up to <n> candidates. Increasing <n> above 10 will take
|
||||
up to _<n>_ candidates. Increasing _<n>_ above 10 will take
|
||||
slightly longer but may produce a more accurate result.
|
||||
An <n> of 0 will cause only exact matches to be output.
|
||||
An _<n>_ of 0 will cause only exact matches to be output.
|
||||
|
||||
--exact-match::
|
||||
`--exact-match`::
|
||||
Only output exact matches (a tag directly references the
|
||||
supplied commit). This is a synonym for --candidates=0.
|
||||
supplied commit). This is a synonym for `--candidates=0`.
|
||||
|
||||
--debug::
|
||||
`--debug`::
|
||||
Verbosely display information about the searching strategy
|
||||
being employed to standard error. The tag name will still
|
||||
be printed to standard out.
|
||||
|
||||
--long::
|
||||
`--long`::
|
||||
Always output the long format (the tag, the number of commits
|
||||
and the abbreviated commit name) even when it matches a tag.
|
||||
This is useful when you want to see parts of the commit object name
|
||||
|
|
@ -94,8 +94,8 @@ OPTIONS
|
|||
describe such a commit as v1.2-0-gdeadbee (0th commit since tag v1.2
|
||||
that points at object deadbee....).
|
||||
|
||||
--match <pattern>::
|
||||
Only consider tags matching the given `glob(7)` pattern,
|
||||
`--match <pattern>`::
|
||||
Only consider tags matching the given `glob`(7) pattern,
|
||||
excluding the "refs/tags/" prefix. If used with `--all`, it also
|
||||
considers local branches and remote-tracking references matching the
|
||||
pattern, excluding respectively "refs/heads/" and "refs/remotes/"
|
||||
|
|
@ -104,22 +104,22 @@ OPTIONS
|
|||
matching any of the patterns will be considered. Use `--no-match` to
|
||||
clear and reset the list of patterns.
|
||||
|
||||
--exclude <pattern>::
|
||||
Do not consider tags matching the given `glob(7)` pattern, excluding
|
||||
`--exclude <pattern>`::
|
||||
Do not consider tags matching the given `glob`(7) pattern, excluding
|
||||
the "refs/tags/" prefix. If used with `--all`, it also does not consider
|
||||
local branches and remote-tracking references matching the pattern,
|
||||
excluding respectively "refs/heads/" and "refs/remotes/" prefix;
|
||||
excluding respectively "`refs/heads/`" and "`refs/remotes/`" prefix;
|
||||
references of other types are never considered. If given multiple times,
|
||||
a list of patterns will be accumulated and tags matching any of the
|
||||
patterns will be excluded. When combined with --match a tag will be
|
||||
considered when it matches at least one --match pattern and does not
|
||||
match any of the --exclude patterns. Use `--no-exclude` to clear and
|
||||
patterns will be excluded. When combined with `--match` a tag will be
|
||||
considered when it matches at least one `--match` pattern and does not
|
||||
match any of the `--exclude` patterns. Use `--no-exclude` to clear and
|
||||
reset the list of patterns.
|
||||
|
||||
--always::
|
||||
`--always`::
|
||||
Show uniquely abbreviated commit object as fallback.
|
||||
|
||||
--first-parent::
|
||||
`--first-parent`::
|
||||
Follow only the first parent commit upon seeing a merge commit.
|
||||
This is useful when you wish to not match tags on branches merged
|
||||
in the history of the target commit.
|
||||
|
|
@ -139,8 +139,8 @@ an abbreviated object name for the commit itself ("2414721")
|
|||
at the end.
|
||||
|
||||
The number of additional commits is the number
|
||||
of commits which would be displayed by "git log v1.0.4..parent".
|
||||
The hash suffix is "-g" + an unambiguous abbreviation for the tip commit
|
||||
of commits which would be displayed by `git log v1.0.4..parent`.
|
||||
The hash suffix is "`-g`" + an unambiguous abbreviation for the tip commit
|
||||
of parent (which was `2414721b194453f058079d897d13c4e377f92dc6`). The
|
||||
length of the abbreviation scales as the repository grows, using the
|
||||
approximate number of objects in the repository and a bit of math
|
||||
|
|
@ -149,12 +149,12 @@ The "g" prefix stands for "git" and is used to allow describing the version of
|
|||
a software depending on the SCM the software is managed with. This is useful
|
||||
in an environment where people may use different SCMs.
|
||||
|
||||
Doing a 'git describe' on a tag-name will just show the tag name:
|
||||
Doing a `git describe` on a tag-name will just show the tag name:
|
||||
|
||||
[torvalds@g5 git]$ git describe v1.0.4
|
||||
v1.0.4
|
||||
|
||||
With --all, the command can use branch heads as references, so
|
||||
With `--all`, the command can use branch heads as references, so
|
||||
the output shows the reference path as well:
|
||||
|
||||
[torvalds@g5 git]$ git describe --all --abbrev=4 v1.0.5^2
|
||||
|
|
@ -163,7 +163,7 @@ the output shows the reference path as well:
|
|||
[torvalds@g5 git]$ git describe --all --abbrev=4 HEAD^
|
||||
heads/lt/describe-7-g975b
|
||||
|
||||
With --abbrev set to 0, the command can be used to find the
|
||||
With `--abbrev` set to 0, the command can be used to find the
|
||||
closest tagname without any suffix:
|
||||
|
||||
[torvalds@g5 git]$ git describe --abbrev=0 v1.0.5^2
|
||||
|
|
@ -179,13 +179,13 @@ be sufficient to disambiguate these commits.
|
|||
SEARCH STRATEGY
|
||||
---------------
|
||||
|
||||
For each commit-ish supplied, 'git describe' will first look for
|
||||
For each commit-ish supplied, `git describe` will first look for
|
||||
a tag which tags exactly that commit. Annotated tags will always
|
||||
be preferred over lightweight tags, and tags with newer dates will
|
||||
always be preferred over tags with older dates. If an exact match
|
||||
is found, its name will be output and searching will stop.
|
||||
|
||||
If an exact match was not found, 'git describe' will walk back
|
||||
If an exact match was not found, `git describe` will walk back
|
||||
through the commit history to locate an ancestor commit which
|
||||
has been tagged. The ancestor's tag will be output along with an
|
||||
abbreviation of the input commit-ish's SHA-1. If `--first-parent` was
|
||||
|
|
@ -203,7 +203,7 @@ BUGS
|
|||
|
||||
Tree objects as well as tag objects not pointing at commits, cannot be described.
|
||||
When describing blobs, the lightweight tags pointing at blobs are ignored,
|
||||
but the blob is still described as <commit-ish>:<path> despite the lightweight
|
||||
but the blob is still described as `<commit-ish>:<path>` despite the lightweight
|
||||
tag being favorable.
|
||||
|
||||
GIT
|
||||
|
|
|
|||
|
|
@ -7,64 +7,64 @@ git-difftool - Show changes using common diff tools
|
|||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git difftool' [<options>] [<commit> [<commit>]] [--] [<path>...]
|
||||
[synopsis]
|
||||
git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
'git difftool' is a Git command that allows you to compare and edit files
|
||||
between revisions using common diff tools. 'git difftool' is a frontend
|
||||
to 'git diff' and accepts the same options and arguments. See
|
||||
`git difftool` is a Git command that allows you to compare and edit files
|
||||
between revisions using common diff tools. `git difftool` is a frontend
|
||||
to `git diff` and accepts the same options and arguments. See
|
||||
linkgit:git-diff[1].
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-d::
|
||||
--dir-diff::
|
||||
`-d`::
|
||||
`--dir-diff`::
|
||||
Copy the modified files to a temporary location and perform
|
||||
a directory diff on them. This mode never prompts before
|
||||
launching the diff tool.
|
||||
|
||||
-y::
|
||||
--no-prompt::
|
||||
`-y`::
|
||||
`--no-prompt`::
|
||||
Do not prompt before launching a diff tool.
|
||||
|
||||
--prompt::
|
||||
`--prompt`::
|
||||
Prompt before each invocation of the diff tool.
|
||||
This is the default behaviour; the option is provided to
|
||||
override any configuration settings.
|
||||
|
||||
--rotate-to=<file>::
|
||||
Start showing the diff for the given path,
|
||||
`--rotate-to=<file>`::
|
||||
Start showing the diff for _<file>_,
|
||||
the paths before it will move to the end and output.
|
||||
|
||||
--skip-to=<file>::
|
||||
Start showing the diff for the given path, skipping all
|
||||
`--skip-to=<file>`::
|
||||
Start showing the diff for _<file>_, skipping all
|
||||
the paths before it.
|
||||
|
||||
-t <tool>::
|
||||
--tool=<tool>::
|
||||
Use the diff tool specified by <tool>. Valid values include
|
||||
`-t <tool>`::
|
||||
`--tool=<tool>`::
|
||||
Use the diff tool specified by _<tool>_. Valid values include
|
||||
emerge, kompare, meld, and vimdiff. Run `git difftool --tool-help`
|
||||
for the list of valid <tool> settings.
|
||||
for the list of valid _<tool>_ settings.
|
||||
+
|
||||
If a diff tool is not specified, 'git difftool'
|
||||
If a diff tool is not specified, `git difftool`
|
||||
will use the configuration variable `diff.tool`. If the
|
||||
configuration variable `diff.tool` is not set, 'git difftool'
|
||||
configuration variable `diff.tool` is not set, `git difftool`
|
||||
will pick a suitable default.
|
||||
+
|
||||
You can explicitly provide a full path to the tool by setting the
|
||||
configuration variable `difftool.<tool>.path`. For example, you
|
||||
can configure the absolute path to kdiff3 by setting
|
||||
`difftool.kdiff3.path`. Otherwise, 'git difftool' assumes the
|
||||
`difftool.kdiff3.path`. Otherwise, `git difftool` assumes the
|
||||
tool is available in PATH.
|
||||
+
|
||||
Instead of running one of the known diff tools,
|
||||
'git difftool' can be customized to run an alternative program
|
||||
`git difftool` can be customized to run an alternative program
|
||||
by specifying the command line to invoke in a configuration
|
||||
variable `difftool.<tool>.cmd`.
|
||||
+
|
||||
When 'git difftool' is invoked with this tool (either through the
|
||||
When `git difftool` is invoked with this tool (either through the
|
||||
`-t` or `--tool` option or the `diff.tool` configuration variable)
|
||||
the configured command line will be invoked with the following
|
||||
variables available: `$LOCAL` is set to the name of the temporary
|
||||
|
|
@ -74,30 +74,30 @@ of the diff post-image. `$MERGED` is the name of the file which is
|
|||
being compared. `$BASE` is provided for compatibility
|
||||
with custom merge tool commands and has the same value as `$MERGED`.
|
||||
|
||||
--tool-help::
|
||||
`--tool-help`::
|
||||
Print a list of diff tools that may be used with `--tool`.
|
||||
|
||||
--symlinks::
|
||||
--no-symlinks::
|
||||
'git difftool''s default behavior is to create symlinks to the
|
||||
`--symlinks`::
|
||||
`--no-symlinks`::
|
||||
`git difftool`'s default behavior is to create symlinks to the
|
||||
working tree when run in `--dir-diff` mode and the right-hand
|
||||
side of the comparison yields the same content as the file in
|
||||
the working tree.
|
||||
+
|
||||
Specifying `--no-symlinks` instructs 'git difftool' to create copies
|
||||
Specifying `--no-symlinks` instructs `git difftool` to create copies
|
||||
instead. `--no-symlinks` is the default on Windows.
|
||||
|
||||
-x <command>::
|
||||
--extcmd=<command>::
|
||||
`-x <command>`::
|
||||
`--extcmd=<command>`::
|
||||
Specify a custom command for viewing diffs.
|
||||
'git-difftool' ignores the configured defaults and runs
|
||||
`git-difftool` ignores the configured defaults and runs
|
||||
`<command> $LOCAL $REMOTE` when this option is specified.
|
||||
Additionally, `$BASE` is set in the environment.
|
||||
|
||||
-g::
|
||||
--gui::
|
||||
--no-gui::
|
||||
When 'git-difftool' is invoked with the `-g` or `--gui` option
|
||||
`-g`::
|
||||
`--gui`::
|
||||
`--no-gui`::
|
||||
When `git-difftool` is invoked with the `-g` or `--gui` option
|
||||
the default diff tool will be read from the configured
|
||||
`diff.guitool` variable instead of `diff.tool`. This may be
|
||||
selected automatically using the configuration variable
|
||||
|
|
@ -106,20 +106,20 @@ instead. `--no-symlinks` is the default on Windows.
|
|||
fallback in the order of `merge.guitool`, `diff.tool`,
|
||||
`merge.tool` until a tool is found.
|
||||
|
||||
--trust-exit-code::
|
||||
--no-trust-exit-code::
|
||||
`--trust-exit-code`::
|
||||
`--no-trust-exit-code`::
|
||||
Errors reported by the diff tool are ignored by default.
|
||||
Use `--trust-exit-code` to make 'git-difftool' exit when an
|
||||
Use `--trust-exit-code` to make `git-difftool` exit when an
|
||||
invoked diff tool returns a non-zero exit code.
|
||||
+
|
||||
'git-difftool' will forward the exit code of the invoked tool when
|
||||
`git-difftool` will forward the exit code of the invoked tool when
|
||||
`--trust-exit-code` is used.
|
||||
|
||||
See linkgit:git-diff[1] for the full list of supported options.
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
'git difftool' falls back to 'git mergetool' config variables when the
|
||||
`git difftool` falls back to `git mergetool` config variables when the
|
||||
difftool equivalents have not been defined.
|
||||
|
||||
include::includes/cmd-config-section-rest.adoc[]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,215 @@
|
|||
git-format-rev(1)
|
||||
=================
|
||||
|
||||
NAME
|
||||
----
|
||||
git-format-rev - EXPERIMENTAL: Pretty format revisions on demand
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[synopsis]
|
||||
(EXPERIMENTAL!) git format-rev --stdin-mode=<mode> --format=<pretty> [--[no-]notes=<ref>] [-z] [--[no-]null-output] [--[no-]null-input]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
Pretty format revisions from standard input.
|
||||
|
||||
THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
`--stdin-mode=<mode>`::
|
||||
How to interpret standard input data:
|
||||
+
|
||||
--
|
||||
`revs`;; Each line or record (see the <<io,INPUT AND OUTPUT FORMATS>>
|
||||
section) is interpreted as a commit. Any kind of revision
|
||||
expression can be used (see linkgit:gitrevisions[7]). Annotated
|
||||
tags are peeled (see linkgit:gitglossary[7]).
|
||||
+
|
||||
The argument `rev` is also accepted.
|
||||
|
||||
`text`;; Formats all commit object names found in freeform text. These
|
||||
must the full object names, i.e. abbreviated hexidecimal object
|
||||
names will not be interpreted.
|
||||
+
|
||||
Anything that is parsed as an object name but that is not found to be a
|
||||
commit object name is left alone (echoed).
|
||||
--
|
||||
|
||||
`--format=<pretty>`::
|
||||
Pretty format string.
|
||||
|
||||
`--notes=<ref>`::
|
||||
`--no-notes`::
|
||||
Custom notes ref. Notes are displayed when using the `%N`
|
||||
atom. See linkgit:git-notes[1].
|
||||
|
||||
`-z`::
|
||||
`--null`::
|
||||
Use _NUL_ character to terminate both input and output instead
|
||||
of newline. This option cannot be negated.
|
||||
+
|
||||
This is useful if both the input and output could contain newlines or if
|
||||
the input to this command also uses _NUL_ character termination; see the
|
||||
<<io,INPUT AND OUTPUT FORMATS>> section below.
|
||||
+
|
||||
The mode `--stdin-mode=text` can have use for this option when it needs
|
||||
to process input like for example `git last-modified -z`; see the
|
||||
<<examples,EXAMPLES>> section below.
|
||||
|
||||
`--null-output`::
|
||||
`--no-null-output`::
|
||||
Use _NUL_ character to terminate output instead of newline. The
|
||||
default is `--no-null-output`.
|
||||
+
|
||||
This is useful if the output could contain newlines, for example if the
|
||||
`%n` (newline) atom is used.
|
||||
|
||||
`--null-input`::
|
||||
`--no-null-input`::
|
||||
Use _NUL_ character to terminate input instead of newline. The
|
||||
default is `--no-null-input`.
|
||||
+
|
||||
This is useful if the input revision expressions could contain newlines.
|
||||
|
||||
[[io]]
|
||||
INPUT AND OUTPUT FORMAT
|
||||
-----------------------
|
||||
|
||||
The command uses newlines for both input and output termination by
|
||||
default. See the `-z`, `--null-output`, and `--null-input` options for
|
||||
using _NUL_ character as the terminator.
|
||||
|
||||
The mode `--stdin-mode=revs` outputs one formatted commit followed by
|
||||
the terminator. This could either be called a _line_ or a _record_ in
|
||||
case "line" is too suggestive of newline termination.
|
||||
|
||||
Note that this means that the terminator character (newline or _NUL_)
|
||||
acts as a _terminator_, not a _separator_. In other words, the final
|
||||
line or record is also terminated by the terminator character.
|
||||
|
||||
The mode `--stdin-mode=text` replaces each object name with the
|
||||
formatted commit, i.e. the format `%s` would transform some commit
|
||||
object name to `<subject>` without any termination. Like this:
|
||||
|
||||
----
|
||||
Did we not fix this in "<subject>"?
|
||||
----
|
||||
|
||||
It is safe to interactively read and write from this command since each
|
||||
record is immediately flushed.
|
||||
|
||||
[[examples]]
|
||||
EXAMPLES
|
||||
--------
|
||||
|
||||
The command linkgit:git-last-modified[1] shows the commit that each file
|
||||
was last modified in.
|
||||
|
||||
----
|
||||
$ git last-modified -- README.md Makefile
|
||||
7798034171030be0909c56377a4e0e10e6d2df93 Makefile
|
||||
c50fbb2dd225e7e82abba4380423ae105089f4d7 README.md
|
||||
----
|
||||
|
||||
We can pipe the result to this command in order to replace the object
|
||||
name with the commit author.
|
||||
|
||||
----
|
||||
$ git last-modified -- README.md Makefile |
|
||||
git format-rev --stdin-mode=text --format=%an
|
||||
Junio C Hamano Makefile
|
||||
Todd Zullinger README.md
|
||||
----
|
||||
|
||||
Another example is _formatting commits in commit messages_. Given this commit message:
|
||||
|
||||
----
|
||||
Fix off-by-one error
|
||||
|
||||
Fix off-by-one error introduced in
|
||||
e83c5163316f89bfbde7d9ab23ca2e25604af290.
|
||||
|
||||
We thought we fixed this in 5569bf9bbedd63a00780fc5c110e0cfab3aa97b9 but
|
||||
that only covered 1/3 of the faulty cases.
|
||||
----
|
||||
|
||||
We can format the commits and use par(1) to reflow the text, say in a
|
||||
`commit-msg` hook:
|
||||
|
||||
----
|
||||
$ git config set hook.reference-commits.event commit-msg
|
||||
$ git config set hook.reference-commits.command reference-commits
|
||||
$ cat $(which reference-commits)
|
||||
#/bin/sh
|
||||
|
||||
msg="$1"
|
||||
rewritten=$(mktemp)
|
||||
git format-rev --stdin-mode=text --format=reference <"$msg" |
|
||||
par >"$rewritten"
|
||||
mv "$rewritten" "$msg"
|
||||
----
|
||||
|
||||
Which will produce something like this:
|
||||
|
||||
----
|
||||
Fix off-by-one error
|
||||
|
||||
Fix off-by-one error introduced in e83c5163316 (Implement better memory
|
||||
allocator, 2005-04-07).
|
||||
|
||||
We thought we fixed this in 5569bf9bbed (Fix memory allocator,
|
||||
2005-06-22) but that only covered 1/3 of the faulty cases.
|
||||
----
|
||||
|
||||
DISCUSSION
|
||||
----------
|
||||
|
||||
This command lets you format any number of revisions in any order
|
||||
through one command invocation. Consider the
|
||||
linkgit:git-last-modified[1] case from the <<examples,EXAMPLES>> section
|
||||
above:
|
||||
|
||||
1. There might be hundreds of files
|
||||
2. Commits can be repeated, i.e. two or more files were last modified in
|
||||
the same commit
|
||||
|
||||
Two widely-used commands which pretty formats commits are
|
||||
linkgit:git-log[1] and linkgit:git-show[1]. It turns out that they are
|
||||
not a good fit for the above use case.
|
||||
|
||||
- The output of linkgit:git-last-modified[1] would have to be processed
|
||||
in stages since you need to transform the first column separately and
|
||||
then link the author to the filename. But this is surmountable.
|
||||
- You can feed each commit to `git show` or `git log --no-walk -1`. But
|
||||
that means that you need to create a process for each line.
|
||||
- Let’s say that you want to use one process, not one per line. So you
|
||||
want to feed all the commits to the command. Now you face the problem
|
||||
that you have to feed all the commits to the commands before you get
|
||||
any output (this is also the case for the `--stdin` modes). In other
|
||||
words, you cannot loop through each line, get the author for the
|
||||
commit, and output the author and the filename. You need to feed all
|
||||
the commits, get back all the output, and match the output with the
|
||||
filename.
|
||||
- But the next problem is that commands will deduplicate the input and
|
||||
only output one commit one single time only. Thus you cannot make the
|
||||
output order match the input order, since a commit could have been
|
||||
repeated in the original input.
|
||||
|
||||
In short, it is straightforward to use these two commands if you use one
|
||||
process per line. It is much more work if you just want to use one
|
||||
process, but still doable. In contrast, this problem is solved with just
|
||||
another shell pipeline with this command.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkgit:git-name-rev[1],
|
||||
linkgit:git-log[1].
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the linkgit:git[1] suite
|
||||
|
|
@ -8,6 +8,7 @@ git-history - EXPERIMENTAL: Rewrite history
|
|||
SYNOPSIS
|
||||
--------
|
||||
[synopsis]
|
||||
git history fixup <commit> [--dry-run] [--update-refs=(branches|head)] [--reedit-message] [--empty=(drop|keep|abort)]
|
||||
git history reword <commit> [--dry-run] [--update-refs=(branches|head)]
|
||||
git history split <commit> [--dry-run] [--update-refs=(branches|head)] [--] [<pathspec>...]
|
||||
|
||||
|
|
@ -22,8 +23,9 @@ THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
|
|||
This command is related to linkgit:git-rebase[1] in that both commands can be
|
||||
used to rewrite history. There are a couple of major differences though:
|
||||
|
||||
* linkgit:git-history[1] can work in a bare repository as it does not need to
|
||||
touch either the index or the worktree.
|
||||
* Most subcommands of linkgit:git-history[1] can work in a bare repository as
|
||||
they do not need to touch either the index or the worktree. The `fixup`
|
||||
subcommand is an exception to this, as it reads staged changes from the index.
|
||||
* linkgit:git-history[1] does not execute any linkgit:githooks[5] at the
|
||||
current point in time. This may change in the future.
|
||||
* linkgit:git-history[1] by default updates all branches that are descendants
|
||||
|
|
@ -48,11 +50,28 @@ conflicts. This limitation is by design as history rewrites are not intended to
|
|||
be stateful operations. The limitation can be lifted once (if) Git learns about
|
||||
first-class conflicts.
|
||||
|
||||
When using `fixup` with `--empty=drop`, dropping the root commit is not yet
|
||||
supported.
|
||||
|
||||
COMMANDS
|
||||
--------
|
||||
|
||||
The following commands are available to rewrite history in different ways:
|
||||
|
||||
`fixup <commit>`::
|
||||
Apply the currently staged changes to the specified commit. This is
|
||||
similar in nature to `git commit --fixup=<commit>` followed by `git
|
||||
rebase --autosquash <commit>~`. Changes are applied to the target
|
||||
commit by performing a three-way merge between the HEAD commit, the
|
||||
target commit and the tree generated from staged changes.
|
||||
+
|
||||
The commit message and authorship of the target commit are preserved by
|
||||
default, unless you specify `--reedit-message`.
|
||||
+
|
||||
If applying the staged changes would result in a conflict, the command
|
||||
aborts with an error. All branches that are descendants of the original
|
||||
commit are updated to point to the rewritten history.
|
||||
|
||||
`reword <commit>`::
|
||||
Rewrite the commit message of the specified commit. All the other
|
||||
details of this commit remain unchanged. This command will spawn an
|
||||
|
|
@ -87,6 +106,31 @@ OPTIONS
|
|||
objects will be written into the repository, so applying these printed
|
||||
ref updates is generally safe.
|
||||
|
||||
`--reedit-message`::
|
||||
Open an editor to modify the target commit's message.
|
||||
|
||||
`--empty=(drop|keep|abort)`::
|
||||
Control what happens when a commit becomes empty as a result of the
|
||||
fixup. This can happen in two situations:
|
||||
+
|
||||
--
|
||||
* The fixup target itself becomes empty because the staged changes exactly
|
||||
cancel out all changes introduced by that commit.
|
||||
|
||||
* A descendant commit becomes empty during replay because it introduced the
|
||||
same change that was just fixed up into an ancestor.
|
||||
--
|
||||
+
|
||||
With `drop` (the default), empty commits are removed from the rewritten
|
||||
history. Descendants of a dropped target commit are replayed directly onto
|
||||
the target's parent. Note that dropping the root commit is not supported;
|
||||
see LIMITATIONS.
|
||||
+
|
||||
With `keep`, empty commits are retained in the rewritten history as-is.
|
||||
+
|
||||
With `abort`, the command stops with an error if any commit would become
|
||||
empty.
|
||||
|
||||
`--update-refs=(branches|head)`::
|
||||
Control which references will be updated by the command, if any. With
|
||||
`branches`, all local branches that point to commits which are
|
||||
|
|
@ -96,6 +140,36 @@ OPTIONS
|
|||
EXAMPLES
|
||||
--------
|
||||
|
||||
Fixup a commit
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
----------
|
||||
$ git log --oneline --stat
|
||||
abc1234 (HEAD -> main) third
|
||||
third.txt | 1 +
|
||||
def5678 second
|
||||
second.txt | 1 +
|
||||
ghi9012 first
|
||||
first.txt | 1 +
|
||||
|
||||
$ echo "change" >>unrelated.txt
|
||||
$ git add unrelated.txt
|
||||
$ git history fixup ghi9012
|
||||
|
||||
$ git log --oneline --stat
|
||||
jkl3456 (HEAD -> main) third
|
||||
third.txt | 1 +
|
||||
mno7890 second
|
||||
second.txt | 1 +
|
||||
pqr1234 first
|
||||
first.txt | 1 +
|
||||
unrelated.txt | 1 +
|
||||
----------
|
||||
|
||||
The staged addition of `unrelated.txt` has been incorporated into the `first`
|
||||
commit. All descendant commits have been replayed on top of the rewritten
|
||||
history.
|
||||
|
||||
Split a commit
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ git-hook - Run git hooks
|
|||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git hook' run [--allow-unknown-hook-name] [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-args>]
|
||||
'git hook' run [--allow-unknown-hook-name] [--ignore-missing] [--to-stdin=<path>] [(-j|--jobs) <n>]
|
||||
<hook-name> [-- <hook-args>]
|
||||
'git hook' list [--allow-unknown-hook-name] [-z] [--show-scope] <hook-name>
|
||||
|
||||
DESCRIPTION
|
||||
|
|
@ -147,6 +148,23 @@ OPTIONS
|
|||
mirroring the output style of `git config --show-scope`. Traditional
|
||||
hooks from the hookdir are unaffected.
|
||||
|
||||
-j::
|
||||
--jobs::
|
||||
Only valid for `run`.
|
||||
+
|
||||
Specify how many hooks to run simultaneously. If this flag is not specified,
|
||||
the value of the `hook.jobs` config is used, see linkgit:git-config[1]. If
|
||||
neither is specified, defaults to 1 (serial execution).
|
||||
+
|
||||
When greater than 1, it overrides the per-hook `hook.<friendly-name>.parallel`
|
||||
setting, allowing all hooks for the event to run concurrently, even if they
|
||||
are not individually marked as parallel.
|
||||
+
|
||||
Some hooks always run sequentially regardless of this flag or the
|
||||
`hook.jobs` config, because git knows they cannot safely run in parallel:
|
||||
`applypatch-msg`, `pre-commit`, `prepare-commit-msg`, `commit-msg`,
|
||||
`post-commit`, `post-checkout`, and `push-to-checkout`.
|
||||
|
||||
WRAPPERS
|
||||
--------
|
||||
|
||||
|
|
@ -169,7 +187,8 @@ running:
|
|||
git hook run --allow-unknown-hook-name mywrapper-start-tests \
|
||||
# providing something to stdin
|
||||
--stdin some-tempfile-123 \
|
||||
# execute hooks in serial
|
||||
# execute multiple hooks in parallel
|
||||
--jobs 3 \
|
||||
# plus some arguments of your own...
|
||||
-- \
|
||||
--testname bar \
|
||||
|
|
|
|||
|
|
@ -36,14 +36,14 @@ OPTIONS
|
|||
Print out the ref names of any commits that are shown. Possible values
|
||||
are:
|
||||
+
|
||||
----
|
||||
--
|
||||
`short`;; the ref name prefixes `refs/heads/`, `refs/tags/` and
|
||||
`refs/remotes/` are not printed.
|
||||
`full`;; the full ref name (including prefix) is printed.
|
||||
`auto`:: if the output is going to a terminal, the ref names
|
||||
`auto`;; if the output is going to a terminal, the ref names
|
||||
are shown as if `short` were given, otherwise no ref names are
|
||||
shown.
|
||||
----
|
||||
--
|
||||
+
|
||||
The option `--decorate` is short-hand for `--decorate=short`. Default to
|
||||
configuration value of `log.decorate` if configured, otherwise, `auto`.
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ can give `--exclude-per-directory=.gitignore`, and then specify:
|
|||
1. The file specified by the `core.excludesfile` configuration
|
||||
variable, if exists, or the `$XDG_CONFIG_HOME/git/ignore` file.
|
||||
|
||||
2. The `$GIT_DIR/info/exclude` file.
|
||||
2. The `$GIT_COMMON_DIR/info/exclude` file.
|
||||
|
||||
via the `--exclude-from=` option.
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,11 @@ SYNOPSIS
|
|||
[verse]
|
||||
'git multi-pack-index' [<options>] write [--preferred-pack=<pack>]
|
||||
[--[no-]bitmap] [--[no-]incremental] [--[no-]stdin-packs]
|
||||
[--refs-snapshot=<path>]
|
||||
[--refs-snapshot=<path>] [--[no-]write-chain-file]
|
||||
[--base=<checksum>]
|
||||
'git multi-pack-index' [<options>] compact [--[no-]incremental]
|
||||
[--[no-]bitmap] <from> <to>
|
||||
[--[no-]bitmap] [--base=<checksum>] [--[no-]write-chain-file]
|
||||
<from> <to>
|
||||
'git multi-pack-index' [<options>] verify
|
||||
'git multi-pack-index' [<options>] expire
|
||||
'git multi-pack-index' [<options>] repack [--batch-size=<size>]
|
||||
|
|
@ -83,6 +85,20 @@ marker).
|
|||
and packs not present in an existing MIDX layer.
|
||||
Migrates non-incremental MIDXs to incremental ones when
|
||||
necessary.
|
||||
|
||||
--[no-]write-chain-file::
|
||||
When used with `--incremental`, write a new MIDX layer
|
||||
but do not update the multi-pack-index-chain file.
|
||||
The checksum of the new layer is printed to standard
|
||||
output, allowing the caller to assemble and write the
|
||||
chain itself. Requires `--incremental`.
|
||||
|
||||
--base=<checksum>::
|
||||
Specify the checksum of an existing MIDX layer to use
|
||||
as the base when writing a new incremental layer.
|
||||
The special value `none` indicates that the new layer
|
||||
should have no base (i.e., it becomes a root layer).
|
||||
Requires `--no-write-chain-file`.
|
||||
--
|
||||
|
||||
compact::
|
||||
|
|
@ -97,6 +113,18 @@ compact::
|
|||
|
||||
--[no-]bitmap::
|
||||
Control whether or not a multi-pack bitmap is written.
|
||||
|
||||
--[no-]write-chain-file::
|
||||
When used with `--incremental`, write a new compacted
|
||||
MIDX layer but do not update the multi-pack-index-chain
|
||||
file. The checksum of the new layer is printed to
|
||||
standard output. Requires `--incremental`.
|
||||
|
||||
--base=<checksum>::
|
||||
Specify the checksum of an existing MIDX layer to use
|
||||
as the base for the compacted result, instead of using
|
||||
the immediate parent of `<from>`. The special value
|
||||
`none` indicates that the result should have no base.
|
||||
--
|
||||
+
|
||||
Note that the compact command requires writing a version-2 midx that
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ git-range-diff - Compare two commit ranges (e.g. two versions of a branch)
|
|||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git range-diff' [--color=[<when>]] [--no-color] [<diff-options>]
|
||||
[synopsis]
|
||||
git range-diff [--color=[<when>]] [--no-color] [<diff-options>]
|
||||
[--no-dual-color] [--creation-factor=<factor>]
|
||||
[--left-only | --right-only] [--diff-merges=<format>]
|
||||
[--remerge-diff]
|
||||
|
|
@ -21,14 +21,14 @@ DESCRIPTION
|
|||
This command shows the differences between two versions of a patch
|
||||
series, or more generally, two commit ranges (ignoring merge commits).
|
||||
|
||||
In the presence of `<path>` arguments, these commit ranges are limited
|
||||
In the presence of _<path>_ arguments, these commit ranges are limited
|
||||
accordingly.
|
||||
|
||||
To that end, it first finds pairs of commits from both commit ranges
|
||||
that correspond with each other. Two commits are said to correspond when
|
||||
the diff between their patches (i.e. the author information, the commit
|
||||
message and the commit diff) is reasonably small compared to the
|
||||
patches' size. See ``Algorithm`` below for details.
|
||||
patches' size. See 'Algorithm' below for details.
|
||||
|
||||
Finally, the list of matching commits is shown in the order of the
|
||||
second commit range, with unmatched commits being inserted just after
|
||||
|
|
@ -37,7 +37,7 @@ all of their ancestors have been shown.
|
|||
There are three ways to specify the commit ranges:
|
||||
|
||||
- `<range1> <range2>`: Either commit range can be of the form
|
||||
`<base>..<rev>`, `<rev>^!` or `<rev>^-<n>`. See `SPECIFYING RANGES`
|
||||
`<base>..<rev>`, `<rev>^!` or `<rev>^-<n>`. See 'SPECIFYING RANGES'
|
||||
in linkgit:gitrevisions[7] for more details.
|
||||
|
||||
- `<rev1>...<rev2>`. This is equivalent to
|
||||
|
|
@ -48,7 +48,7 @@ There are three ways to specify the commit ranges:
|
|||
|
||||
OPTIONS
|
||||
-------
|
||||
--no-dual-color::
|
||||
`--no-dual-color`::
|
||||
When the commit diffs differ, `git range-diff` recreates the
|
||||
original diffs' coloring, and adds outer -/+ diff markers with
|
||||
the *background* being red/green to make it easier to see e.g.
|
||||
|
|
@ -56,33 +56,33 @@ OPTIONS
|
|||
+
|
||||
Additionally, the commit diff lines that are only present in the first commit
|
||||
range are shown "dimmed" (this can be overridden using the `color.diff.<slot>`
|
||||
config setting where `<slot>` is one of `contextDimmed`, `oldDimmed` and
|
||||
config setting where _<slot>_ is one of `contextDimmed`, `oldDimmed` and
|
||||
`newDimmed`), and the commit diff lines that are only present in the second
|
||||
commit range are shown in bold (which can be overridden using the config
|
||||
settings `color.diff.<slot>` with `<slot>` being one of `contextBold`,
|
||||
settings `color.diff.<slot>` with _<slot>_ being one of `contextBold`,
|
||||
`oldBold` or `newBold`).
|
||||
+
|
||||
This is known to `range-diff` as "dual coloring". Use `--no-dual-color`
|
||||
to revert to color all lines according to the outer diff markers
|
||||
(and completely ignore the inner diff when it comes to color).
|
||||
|
||||
--creation-factor=<percent>::
|
||||
Set the creation/deletion cost fudge factor to `<percent>`.
|
||||
`--creation-factor=<percent>`::
|
||||
Set the creation/deletion cost fudge factor to _<percent>_.
|
||||
Defaults to 60. Try a larger value if `git range-diff` erroneously
|
||||
considers a large change a total rewrite (deletion of one commit
|
||||
and addition of another), and a smaller one in the reverse case.
|
||||
See the ``Algorithm`` section below for an explanation of why this is
|
||||
See the 'Algorithm' section below for an explanation of why this is
|
||||
needed.
|
||||
|
||||
--left-only::
|
||||
`--left-only`::
|
||||
Suppress commits that are missing from the first specified range
|
||||
(or the "left range" when using the `<rev1>...<rev2>` format).
|
||||
(or the "left range" when using the `<rev1>...<rev2>` form).
|
||||
|
||||
--right-only::
|
||||
`--right-only`::
|
||||
Suppress commits that are missing from the second specified range
|
||||
(or the "right range" when using the `<rev1>...<rev2>` format).
|
||||
(or the "right range" when using the `<rev1>...<rev2>` form).
|
||||
|
||||
--diff-merges=<format>::
|
||||
`--diff-merges=<format>`::
|
||||
Instead of ignoring merge commits, generate diffs for them using the
|
||||
corresponding `--diff-merges=<format>` option of linkgit:git-log[1],
|
||||
and include them in the comparison.
|
||||
|
|
@ -93,30 +93,30 @@ have produced. In other words, if a merge commit is the result of a
|
|||
non-conflicting `git merge`, the `remerge` mode will represent it with an empty
|
||||
diff.
|
||||
|
||||
--remerge-diff::
|
||||
`--remerge-diff`::
|
||||
Convenience option, equivalent to `--diff-merges=remerge`.
|
||||
|
||||
--notes[=<ref>]::
|
||||
--no-notes::
|
||||
`--notes[=<ref>]`::
|
||||
`--no-notes`::
|
||||
This flag is passed to the `git log` program
|
||||
(see linkgit:git-log[1]) that generates the patches.
|
||||
|
||||
<range1> <range2>::
|
||||
`<range1> <range2>`::
|
||||
Compare the commits specified by the two ranges, where
|
||||
`<range1>` is considered an older version of `<range2>`.
|
||||
_<range1>_ is considered an older version of _<range2>_.
|
||||
|
||||
<rev1>...<rev2>::
|
||||
`<rev1>...<rev2>`::
|
||||
Equivalent to passing `<rev2>..<rev1>` and `<rev1>..<rev2>`.
|
||||
|
||||
<base> <rev1> <rev2>::
|
||||
`<base> <rev1> <rev2>`::
|
||||
Equivalent to passing `<base>..<rev1>` and `<base>..<rev2>`.
|
||||
Note that `<base>` does not need to be the exact branch point
|
||||
Note that _<base>_ does not need to be the exact branch point
|
||||
of the branches. Example: after rebasing a branch `my-topic`,
|
||||
`git range-diff my-topic@{u} my-topic@{1} my-topic` would
|
||||
show the differences introduced by the rebase.
|
||||
|
||||
`git range-diff` also accepts the regular diff options (see
|
||||
linkgit:git-diff[1]), most notably the `--color=[<when>]` and
|
||||
linkgit:git-diff[1]), most notably the `--color[=<when>]` and
|
||||
`--no-color` options. These options are used when generating the "diff
|
||||
between patches", i.e. to compare the author, commit message and diff of
|
||||
corresponding old/new commits. There is currently no means to tweak most of the
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ SYNOPSIS
|
|||
[verse]
|
||||
'git repack' [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]
|
||||
[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]
|
||||
[--write-midx] [--name-hash-version=<n>] [--path-walk]
|
||||
[--write-midx[=<mode>]] [--name-hash-version=<n>] [--path-walk]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
|
@ -250,9 +250,47 @@ pack as the preferred pack for object selection by the MIDX (see
|
|||
linkgit:git-multi-pack-index[1]).
|
||||
|
||||
-m::
|
||||
--write-midx::
|
||||
--write-midx[=<mode>]::
|
||||
Write a multi-pack index (see linkgit:git-multi-pack-index[1])
|
||||
containing the non-redundant packs.
|
||||
containing the non-redundant packs. The following modes are
|
||||
available:
|
||||
+
|
||||
--
|
||||
`default`;;
|
||||
Write a single MIDX covering all packs. This is the
|
||||
default when `--write-midx` is given without an
|
||||
explicit mode.
|
||||
|
||||
`incremental`;;
|
||||
Write an incremental MIDX chain instead of a single
|
||||
flat MIDX.
|
||||
+
|
||||
Without `--geometric`, a new MIDX layer is appended to the existing
|
||||
chain (or a new chain is started) containing whatever packs were written
|
||||
by the repack. Existing layers are preserved as-is.
|
||||
+
|
||||
When combined with `--geometric`, the incremental mode maintains a chain
|
||||
of MIDX layers that is compacted over time using a geometric merging
|
||||
strategy. Each repack creates a new tip layer containing the newly
|
||||
written pack(s). Adjacent layers are then merged whenever the newer
|
||||
layer's object count exceeds `1/repack.midxSplitFactor` of the next
|
||||
deeper layer's count. Layers that do not meet this condition are
|
||||
retained as-is.
|
||||
+
|
||||
The result is that newer (tip) layers tend to contain many small packs
|
||||
with relatively few objects, while older (deeper) layers contain fewer,
|
||||
larger packs covering more objects. Because compaction is driven by the
|
||||
tip of the chain, newer layers are also rewritten more frequently than
|
||||
older ones, which are only touched when enough objects have accumulated
|
||||
to justify merging into them. This keeps the total number of layers
|
||||
logarithmic relative to the total number of objects.
|
||||
+
|
||||
Only packs in the tip MIDX layer are considered as candidates for the
|
||||
geometric repack; packs in deeper layers are left untouched. If the tip
|
||||
layer contains fewer packs than `repack.midxNewLayerThreshold`, those
|
||||
packs are excluded from the geometry entirely, and a new layer is
|
||||
created for any new pack(s) without disturbing the existing chain.
|
||||
--
|
||||
|
||||
--name-hash-version=<n>::
|
||||
Provide this argument to the underlying `git pack-objects` process.
|
||||
|
|
|
|||
|
|
@ -145,6 +145,13 @@ commit instead of the replaced commit.
|
|||
There may be other problems when using 'git rev-list' related to
|
||||
pending objects.
|
||||
|
||||
CAVEATS
|
||||
-------
|
||||
|
||||
The existence of replace objects or commit grafts turns off reading or
|
||||
writing to the commit-graph, which can cause performance issues. See
|
||||
linkgit:git-commit-graph[1].
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkgit:git-hash-object[1]
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ given, otherwise from the index.
|
|||
+
|
||||
As a special case, you may use `"<rev-A>...<rev-B>"` as a shortcut for the
|
||||
merge base of _<rev-A>_ and _<rev-B>_ if there is exactly one merge base. You can
|
||||
leave out at most one of _<rev-A>__ and _<rev-B>_, in which case it defaults to `HEAD`.
|
||||
leave out at most one of _<rev-A>_ and _<rev-B>_, in which case it defaults to `HEAD`.
|
||||
|
||||
`-p`::
|
||||
`--patch`::
|
||||
|
|
|
|||
|
|
@ -3,63 +3,63 @@ git-shortlog(1)
|
|||
|
||||
NAME
|
||||
----
|
||||
git-shortlog - Summarize 'git log' output
|
||||
git-shortlog - Summarize `git log` output
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git shortlog' [<options>] [<revision-range>] [[--] <path>...]
|
||||
git log --pretty=short | 'git shortlog' [<options>]
|
||||
[synopsis]
|
||||
git shortlog [<options>] [<revision-range>] [[--] <path>...]
|
||||
git log --pretty=short | git shortlog [<options>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Summarizes 'git log' output in a format suitable for inclusion
|
||||
Summarizes `git log` output in a format suitable for inclusion
|
||||
in release announcements. Each commit will be grouped by author and title.
|
||||
|
||||
Additionally, "[PATCH]" will be stripped from the commit description.
|
||||
|
||||
If no revisions are passed on the command line and either standard input
|
||||
is not a terminal or there is no current branch, 'git shortlog' will
|
||||
is not a terminal or there is no current branch, `git shortlog` will
|
||||
output a summary of the log read from standard input, without
|
||||
reference to the current repository.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
-n::
|
||||
--numbered::
|
||||
`-n`::
|
||||
`--numbered`::
|
||||
Sort output according to the number of commits per author instead
|
||||
of author alphabetic order.
|
||||
|
||||
-s::
|
||||
--summary::
|
||||
`-s`::
|
||||
`--summary`::
|
||||
Suppress commit description and provide a commit count summary only.
|
||||
|
||||
-e::
|
||||
--email::
|
||||
`-e`::
|
||||
`--email`::
|
||||
Show the email address of each author.
|
||||
|
||||
--format[=<format>]::
|
||||
`--format[=<format>]`::
|
||||
Instead of the commit subject, use some other information to
|
||||
describe each commit. '<format>' can be any string accepted
|
||||
by the `--format` option of 'git log', such as '* [%h] %s'.
|
||||
(See the "PRETTY FORMATS" section of linkgit:git-log[1].)
|
||||
describe each commit. _<format>_ can be any string accepted
|
||||
by the `--format` option of `git log`, such as '* [%h] %s'.
|
||||
(See the 'PRETTY FORMATS' section of linkgit:git-log[1].)
|
||||
+
|
||||
Each pretty-printed commit will be rewrapped before it is shown.
|
||||
|
||||
--date=<format>::
|
||||
`--date=<format>`::
|
||||
Show dates formatted according to the given date string. (See
|
||||
the `--date` option in the "Commit Formatting" section of
|
||||
the `--date` option in the 'Commit Formatting' section of
|
||||
linkgit:git-log[1]). Useful with `--group=format:<format>`.
|
||||
|
||||
--group=<type>::
|
||||
Group commits based on `<type>`. If no `--group` option is
|
||||
specified, the default is `author`. `<type>` is one of:
|
||||
`--group=<type>`::
|
||||
Group commits based on _<type>_. If no `--group` option is
|
||||
specified, the default is `author`. _<type>_ is one of:
|
||||
+
|
||||
--
|
||||
- `author`, commits are grouped by author
|
||||
- `committer`, commits are grouped by committer (the same as `-c`)
|
||||
- `trailer:<field>`, the `<field>` is interpreted as a case-insensitive
|
||||
- `trailer:<field>`, the _<field>_ is interpreted as a case-insensitive
|
||||
commit message trailer (see linkgit:git-interpret-trailers[1]). For
|
||||
example, if your project uses `Reviewed-by` trailers, you might want
|
||||
to see who has been reviewing with
|
||||
|
|
@ -76,7 +76,7 @@ unless the `--email` option is specified. If the value cannot be parsed
|
|||
as an identity, it will be taken literally and completely.
|
||||
|
||||
- `format:<format>`, any string accepted by the `--format` option of
|
||||
'git log'. (See the "PRETTY FORMATS" section of
|
||||
`git log`. (See the 'PRETTY FORMATS' section of
|
||||
linkgit:git-log[1].)
|
||||
--
|
||||
+
|
||||
|
|
@ -85,11 +85,11 @@ value (but again, only once per unique value in that commit). For
|
|||
example, `git shortlog --group=author --group=trailer:co-authored-by`
|
||||
counts both authors and co-authors.
|
||||
|
||||
-c::
|
||||
--committer::
|
||||
`-c`::
|
||||
`--committer`::
|
||||
This is an alias for `--group=committer`.
|
||||
|
||||
-w[<width>[,<indent1>[,<indent2>]]]::
|
||||
`-w[<width>[,<indent1>[,<indent2>]]]`::
|
||||
Linewrap the output by wrapping each line at `width`. The first
|
||||
line of each entry is indented by `indent1` spaces, and the second
|
||||
and subsequent lines are indented by `indent2` spaces. `width`,
|
||||
|
|
@ -98,16 +98,16 @@ counts both authors and co-authors.
|
|||
If width is `0` (zero) then indent the lines of the output without wrapping
|
||||
them.
|
||||
|
||||
<revision-range>::
|
||||
`<revision-range>`::
|
||||
Show only commits in the specified revision range. When no
|
||||
<revision-range> is specified, it defaults to `HEAD` (i.e. the
|
||||
_<revision-range>_ is specified, it defaults to `HEAD` (i.e. the
|
||||
whole history leading to the current commit). `origin..HEAD`
|
||||
specifies all the commits reachable from the current commit
|
||||
(i.e. `HEAD`), but not from `origin`. For a complete list of
|
||||
ways to spell <revision-range>, see the "Specifying Ranges"
|
||||
ways to spell _<revision-range>_, see the 'Specifying Ranges'
|
||||
section of linkgit:gitrevisions[7].
|
||||
|
||||
[--] <path>...::
|
||||
`[--] <path>...`::
|
||||
Consider only commits that are enough to explain how the files
|
||||
that match the specified paths came to be.
|
||||
+
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ git stash list [<log-options>]
|
|||
git stash show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]
|
||||
git stash drop [-q | --quiet] [<stash>]
|
||||
git stash pop [--index] [-q | --quiet] [<stash>]
|
||||
git stash apply [--index] [-q | --quiet] [<stash>]
|
||||
git stash apply [--index] [-q | --quiet] [--label-ours=<label>] [--label-theirs=<label>] [--label-base=<label>] [<stash>]
|
||||
git stash branch <branchname> [<stash>]
|
||||
git stash [push] [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
|
||||
[-u | --include-untracked] [-a | --all] [(-m | --message) <message>]
|
||||
|
|
@ -195,6 +195,15 @@ the index's ones. However, this can fail, when you have conflicts
|
|||
(which are stored in the index, where you therefore can no longer
|
||||
apply the changes as they were originally).
|
||||
|
||||
`--label-ours=<label>`::
|
||||
`--label-theirs=<label>`::
|
||||
`--label-base=<label>`::
|
||||
These options are only valid for the `apply` command.
|
||||
+
|
||||
Use the given labels in conflict markers instead of the default
|
||||
"Updated upstream", "Stashed changes", and "Stash base".
|
||||
`--label-base` only has an effect with merge.conflictStyle=diff3.
|
||||
|
||||
`-k`::
|
||||
`--keep-index`::
|
||||
`--no-keep-index`::
|
||||
|
|
|
|||
|
|
@ -439,7 +439,7 @@ Any other arguments are passed directly to 'git log'
|
|||
'show-ignore'::
|
||||
Recursively finds and lists the svn:ignore and svn:global-ignores
|
||||
properties on directories. The output is suitable for appending to
|
||||
the $GIT_DIR/info/exclude file.
|
||||
the $GIT_COMMON_DIR/info/exclude file.
|
||||
|
||||
'mkdirs'::
|
||||
Attempts to recreate empty directories that core Git cannot track
|
||||
|
|
|
|||
|
|
@ -123,18 +123,19 @@ variable.
|
|||
|
||||
`-m`::
|
||||
`--merge`::
|
||||
If you have local modifications to one or more files that are
|
||||
different between the current branch and the branch to which
|
||||
you are switching, the command refuses to switch branches in
|
||||
order to preserve your modifications in context. However,
|
||||
with this option, a three-way merge between the current
|
||||
branch, your working tree contents, and the new branch is
|
||||
done, and you will be on the new branch.
|
||||
+
|
||||
When a merge conflict happens, the index entries for conflicting
|
||||
paths are left unmerged, and you need to resolve the conflicts
|
||||
and mark the resolved paths with `git add` (or `git rm` if the merge
|
||||
should result in deletion of the path).
|
||||
If you have local modifications to one or more files that
|
||||
are different between the current branch and the branch to
|
||||
which you are switching, the command normally refuses to
|
||||
switch branches in order to preserve your modifications in
|
||||
context. However, with this option, the conflicting local
|
||||
changes are automatically stashed before the switch and
|
||||
reapplied afterwards. If the local changes do not overlap
|
||||
with the differences between branches, the switch proceeds
|
||||
without stashing. If reapplying the stash results in
|
||||
conflicts, the entry is saved to the stash list. Resolve
|
||||
the conflicts and run `git stash drop` when done, or clear
|
||||
the working tree (e.g. with `git reset --hard`) before
|
||||
running `git stash pop` later to re-apply your changes.
|
||||
|
||||
`--conflict=<style>`::
|
||||
The same as `--merge` option above, but changes the way the
|
||||
|
|
@ -217,15 +218,18 @@ $ git switch mytopic
|
|||
error: You have local changes to 'frotz'; not switching branches.
|
||||
------------
|
||||
|
||||
You can give the `-m` flag to the command, which would try a three-way
|
||||
merge:
|
||||
You can give the `-m` flag to the command, which will carry your local
|
||||
changes to the new branch:
|
||||
|
||||
------------
|
||||
$ git switch -m mytopic
|
||||
Auto-merging frotz
|
||||
Applied autostash.
|
||||
Switched to branch 'mytopic'
|
||||
The following paths have local changes:
|
||||
M frotz
|
||||
------------
|
||||
|
||||
After this three-way merge, the local modifications are _not_
|
||||
After the switch, the local modifications are reapplied and are _not_
|
||||
registered in your index file, so `git diff` would show you what
|
||||
changes you made since the tip of the new branch.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
git-url-parse(1)
|
||||
================
|
||||
|
||||
NAME
|
||||
----
|
||||
git-url-parse - Parse and extract git URL components
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[synopsis]
|
||||
git url-parse [-c <component>] [--] <url>...
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
Git supports many ways to specify URLs, some of them non-standard.
|
||||
For example, git supports the scp style [user@]host:[path] format.
|
||||
This command eases interoperability with git URLs by enabling the
|
||||
parsing and extraction of the components of all git URLs.
|
||||
|
||||
Any syntactically valid URL is parsed, even if the scheme is not one
|
||||
git supports for fetching or pushing.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
`-c <component>`::
|
||||
`--component <component>`::
|
||||
Extract the _<component>_ component from the given Git URLs.
|
||||
_<component>_ can be one of:
|
||||
`scheme`, `user`, `password`, `host`, `port`, `path`.
|
||||
|
||||
OUTPUT
|
||||
------
|
||||
|
||||
When `--component` is given, the requested component of each URL
|
||||
is printed on its own line, in the order the URLs were given. If
|
||||
the URL has no such component (for example, a port in a URL that
|
||||
does not specify one), an empty line is printed in its place.
|
||||
|
||||
When `--component` is not given, no output is produced. The exit
|
||||
status is zero if every URL parses successfully and non-zero
|
||||
otherwise, allowing the command to be used purely as a validator.
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
|
||||
* Print the host name:
|
||||
+
|
||||
------------
|
||||
$ git url-parse --component host https://example.com/user/repo
|
||||
example.com
|
||||
------------
|
||||
|
||||
* Print the path:
|
||||
+
|
||||
------------
|
||||
$ git url-parse --component path https://example.com/user/repo
|
||||
/user/repo
|
||||
$ git url-parse --component path example.com:~user/repo
|
||||
~user/repo
|
||||
$ git url-parse --component path example.com:user/repo
|
||||
/user/repo
|
||||
------------
|
||||
|
||||
* Validate URLs without outputting anything:
|
||||
+
|
||||
------------
|
||||
$ git url-parse https://example.com/user/repo example.com:~user/repo
|
||||
------------
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkgit:git-clone[1],
|
||||
linkgit:git-fetch[1],
|
||||
linkgit:git-config[1]
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the linkgit:git[1] suite
|
||||
|
|
@ -911,7 +911,8 @@ patterns are available:
|
|||
|
||||
- `rust` suitable for source code in the Rust language.
|
||||
|
||||
- `scheme` suitable for source code in the Scheme language.
|
||||
- `scheme` suitable for source code in most Lisp dialects,
|
||||
including Scheme, Emacs Lisp, Common Lisp, and Clojure.
|
||||
|
||||
- `tex` suitable for source code for LaTeX documents.
|
||||
|
||||
|
|
|
|||
|
|
@ -291,14 +291,14 @@ Git index format
|
|||
sequence in variable width encoding. Each string describes the
|
||||
environment where the cache can be used.
|
||||
|
||||
- Stat data of $GIT_DIR/info/exclude. See "Index entry" section from
|
||||
- Stat data of $GIT_COMMON_DIR/info/exclude. See "Index entry" section from
|
||||
ctime field until "file size".
|
||||
|
||||
- Stat data of core.excludesFile
|
||||
|
||||
- 32-bit dir_flags (see struct dir_struct)
|
||||
|
||||
- Hash of $GIT_DIR/info/exclude. A null hash means the file
|
||||
- Hash of $GIT_COMMON_DIR/info/exclude. A null hash means the file
|
||||
does not exist.
|
||||
|
||||
- Hash of core.excludesFile. A null hash means the file does
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ gitignore - Specifies intentionally untracked files to ignore
|
|||
|
||||
SYNOPSIS
|
||||
--------
|
||||
$XDG_CONFIG_HOME/git/ignore, $GIT_DIR/info/exclude, .gitignore
|
||||
$XDG_CONFIG_HOME/git/ignore, $GIT_COMMON_DIR/info/exclude, .gitignore
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
|
@ -34,7 +34,7 @@ precedence, the last matching pattern decides the outcome):
|
|||
includes such `.gitignore` files in its repository, containing patterns for
|
||||
files generated as part of the project build.
|
||||
|
||||
* Patterns read from `$GIT_DIR/info/exclude`.
|
||||
* Patterns read from `$GIT_COMMON_DIR/info/exclude`.
|
||||
|
||||
* Patterns read from the file specified by the configuration
|
||||
variable `core.excludesFile`.
|
||||
|
|
@ -50,7 +50,7 @@ be used.
|
|||
specific to a particular repository but which do not need to be shared
|
||||
with other related repositories (e.g., auxiliary files that live inside
|
||||
the repository but are specific to one user's workflow) should go into
|
||||
the `$GIT_DIR/info/exclude` file.
|
||||
the `$GIT_COMMON_DIR/info/exclude` file.
|
||||
|
||||
* Patterns which a user wants Git to
|
||||
ignore in all situations (e.g., backup or temporary files generated by
|
||||
|
|
@ -97,7 +97,7 @@ PATTERN FORMAT
|
|||
match at any level below the `.gitignore` level.
|
||||
|
||||
- Patterns read from exclude sources that are outside the working tree,
|
||||
such as $GIT_DIR/info/exclude and core.excludesFile, are treated as if
|
||||
such as $GIT_COMMON_DIR/info/exclude and core.excludesFile, are treated as if
|
||||
they are specified at the root of the working tree, i.e. a leading "/"
|
||||
in such patterns anchors the match at the root of the repository.
|
||||
|
||||
|
|
@ -146,8 +146,8 @@ CONFIGURATION
|
|||
|
||||
The optional configuration variable `core.excludesFile` indicates a path to a
|
||||
file containing patterns of file names to exclude, similar to
|
||||
`$GIT_DIR/info/exclude`. Patterns in the exclude file are used in addition to
|
||||
those in `$GIT_DIR/info/exclude`.
|
||||
`$GIT_COMMON_DIR/info/exclude`. Patterns in the exclude file are used in
|
||||
addition to those in `$GIT_COMMON_DIR/info/exclude`.
|
||||
|
||||
NOTES
|
||||
-----
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ with a configuration like so:
|
|||
pattern = "refs/"
|
||||
threshold = now
|
||||
stableThreshold = never
|
||||
sampleRate = 100
|
||||
sampleRate = 1
|
||||
maxMerges = 64
|
||||
----
|
||||
|
||||
|
|
@ -177,7 +177,7 @@ like:
|
|||
pattern = "refs/virtual/([0-9]+)/(heads|tags)/"
|
||||
threshold = now
|
||||
stableThreshold = never
|
||||
sampleRate = 100
|
||||
sampleRate = 1
|
||||
maxMerges = 64
|
||||
----
|
||||
|
||||
|
|
|
|||
|
|
@ -848,6 +848,10 @@ advertised, it can reply with "promisor-remote=<pr-names>" where
|
|||
where `pr-name` is the urlencoded name of a promisor remote the server
|
||||
advertised and the client accepts.
|
||||
|
||||
The promisor remotes that the client accepted will be tried before the
|
||||
other configured promisor remotes when the client attempts to fetch
|
||||
missing objects.
|
||||
|
||||
Note that, everywhere in this document, the ';' and ',' characters
|
||||
MUST be encoded if they appear in `pr-name` or `field-value`.
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ manpages = {
|
|||
'git-for-each-ref.adoc' : 1,
|
||||
'git-for-each-repo.adoc' : 1,
|
||||
'git-format-patch.adoc' : 1,
|
||||
'git-format-rev.adoc' : 1,
|
||||
'git-fsck-objects.adoc' : 1,
|
||||
'git-fsck.adoc' : 1,
|
||||
'git-fsmonitor--daemon.adoc' : 1,
|
||||
|
|
@ -155,6 +156,7 @@ manpages = {
|
|||
'git-update-server-info.adoc' : 1,
|
||||
'git-upload-archive.adoc' : 1,
|
||||
'git-upload-pack.adoc' : 1,
|
||||
'git-url-parse.adoc' : 1,
|
||||
'git-var.adoc' : 1,
|
||||
'git-verify-commit.adoc' : 1,
|
||||
'git-verify-pack.adoc' : 1,
|
||||
|
|
|
|||
35
Makefile
35
Makefile
|
|
@ -283,13 +283,9 @@ include shared.mak
|
|||
# Define SKIP_DASHED_BUILT_INS if you do not need the dashed versions of the
|
||||
# built-ins to be linked/copied at all.
|
||||
#
|
||||
# Define USE_NED_ALLOCATOR if you want to replace the platforms default
|
||||
# memory allocators with the nedmalloc allocator written by Niall Douglas.
|
||||
#
|
||||
# Define OVERRIDE_STRDUP to override the libc version of strdup(3).
|
||||
# This is necessary when using a custom allocator in order to avoid
|
||||
# crashes due to allocation and free working on different 'heaps'.
|
||||
# It's defined automatically if USE_NED_ALLOCATOR is set.
|
||||
#
|
||||
# Define NO_REGEX if your C library lacks regex support with REG_STARTEND
|
||||
# feature.
|
||||
|
|
@ -498,9 +494,9 @@ include shared.mak
|
|||
#
|
||||
# == Optional Rust support ==
|
||||
#
|
||||
# Define WITH_RUST if you want to include features and subsystems written in
|
||||
# Rust into Git. For now, Rust is still an optional feature of the build
|
||||
# process. With Git 3.0 though, Rust will always be enabled.
|
||||
# Define NO_RUST if you want to disable features and subsystems written in Rust
|
||||
# from being compiled into Git. For now, Rust is still an optional feature of
|
||||
# the build process. With Git 3.0 though, Rust will always be enabled.
|
||||
#
|
||||
# Building Rust code requires Cargo.
|
||||
#
|
||||
|
|
@ -872,6 +868,7 @@ TEST_BUILTINS_OBJS += test-submodule-config.o
|
|||
TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o
|
||||
TEST_BUILTINS_OBJS += test-submodule.o
|
||||
TEST_BUILTINS_OBJS += test-subprocess.o
|
||||
TEST_BUILTINS_OBJS += test-synthesize.o
|
||||
TEST_BUILTINS_OBJS += test-trace2.o
|
||||
TEST_BUILTINS_OBJS += test-truncate.o
|
||||
TEST_BUILTINS_OBJS += test-userdiff.o
|
||||
|
|
@ -895,6 +892,7 @@ BUILT_INS += $(patsubst builtin/%.o,git-%$X,$(BUILTIN_OBJS))
|
|||
BUILT_INS += git-cherry$X
|
||||
BUILT_INS += git-cherry-pick$X
|
||||
BUILT_INS += git-format-patch$X
|
||||
BUILT_INS += git-format-rev$X
|
||||
BUILT_INS += git-fsck-objects$X
|
||||
BUILT_INS += git-init$X
|
||||
BUILT_INS += git-maintenance$X
|
||||
|
|
@ -1218,7 +1216,9 @@ LIB_OBJS += object.o
|
|||
LIB_OBJS += odb.o
|
||||
LIB_OBJS += odb/source.o
|
||||
LIB_OBJS += odb/source-files.o
|
||||
LIB_OBJS += odb/source-inmemory.o
|
||||
LIB_OBJS += odb/streaming.o
|
||||
LIB_OBJS += odb/transaction.o
|
||||
LIB_OBJS += oid-array.o
|
||||
LIB_OBJS += oidmap.o
|
||||
LIB_OBJS += oidset.o
|
||||
|
|
@ -1351,7 +1351,7 @@ LIB_OBJS += urlmatch.o
|
|||
LIB_OBJS += usage.o
|
||||
LIB_OBJS += userdiff.o
|
||||
LIB_OBJS += utf8.o
|
||||
ifndef WITH_RUST
|
||||
ifdef NO_RUST
|
||||
LIB_OBJS += varint.o
|
||||
endif
|
||||
LIB_OBJS += version.o
|
||||
|
|
@ -1497,6 +1497,7 @@ BUILTIN_OBJS += builtin/update-ref.o
|
|||
BUILTIN_OBJS += builtin/update-server-info.o
|
||||
BUILTIN_OBJS += builtin/upload-archive.o
|
||||
BUILTIN_OBJS += builtin/upload-pack.o
|
||||
BUILTIN_OBJS += builtin/url-parse.o
|
||||
BUILTIN_OBJS += builtin/var.o
|
||||
BUILTIN_OBJS += builtin/verify-commit.o
|
||||
BUILTIN_OBJS += builtin/verify-pack.o
|
||||
|
|
@ -1511,7 +1512,6 @@ BUILTIN_OBJS += builtin/write-tree.o
|
|||
# upstream unnecessarily (making merging in future changes easier).
|
||||
THIRD_PARTY_SOURCES += compat/inet_ntop.c
|
||||
THIRD_PARTY_SOURCES += compat/inet_pton.c
|
||||
THIRD_PARTY_SOURCES += compat/nedmalloc/%
|
||||
THIRD_PARTY_SOURCES += compat/obstack.%
|
||||
THIRD_PARTY_SOURCES += compat/poll/%
|
||||
THIRD_PARTY_SOURCES += compat/regex/%
|
||||
|
|
@ -1527,6 +1527,7 @@ CLAR_TEST_SUITES += u-hash
|
|||
CLAR_TEST_SUITES += u-hashmap
|
||||
CLAR_TEST_SUITES += u-list-objects-filter-options
|
||||
CLAR_TEST_SUITES += u-mem-pool
|
||||
CLAR_TEST_SUITES += u-odb-inmemory
|
||||
CLAR_TEST_SUITES += u-oid-array
|
||||
CLAR_TEST_SUITES += u-oidmap
|
||||
CLAR_TEST_SUITES += u-oidtree
|
||||
|
|
@ -1590,7 +1591,7 @@ endif
|
|||
ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_APPEND)
|
||||
ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)
|
||||
|
||||
ifdef WITH_RUST
|
||||
ifndef NO_RUST
|
||||
BASIC_CFLAGS += -DWITH_RUST
|
||||
GITLIBS += $(RUST_LIB)
|
||||
ifeq ($(uname_S),Windows)
|
||||
|
|
@ -2267,12 +2268,6 @@ ifdef NATIVE_CRLF
|
|||
BASIC_CFLAGS += -DNATIVE_CRLF
|
||||
endif
|
||||
|
||||
ifdef USE_NED_ALLOCATOR
|
||||
COMPAT_CFLAGS += -Icompat/nedmalloc
|
||||
COMPAT_OBJS += compat/nedmalloc/nedmalloc.o
|
||||
OVERRIDE_STRDUP = YesPlease
|
||||
endif
|
||||
|
||||
ifdef OVERRIDE_STRDUP
|
||||
COMPAT_CFLAGS += -DOVERRIDE_STRDUP
|
||||
COMPAT_OBJS += compat/strdup.o
|
||||
|
|
@ -2671,7 +2666,7 @@ git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS)
|
|||
|
||||
help.sp help.s help.o: command-list.h
|
||||
builtin/bugreport.sp builtin/bugreport.s builtin/bugreport.o: hook-list.h
|
||||
builtin/hook.sp builtin/hook.s builtin/hook.o: hook-list.h
|
||||
hook.sp hook.s hook.o: hook-list.h
|
||||
|
||||
builtin/help.sp builtin/help.s builtin/help.o: config-list.h GIT-PREFIX
|
||||
builtin/help.sp builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \
|
||||
|
|
@ -2983,12 +2978,6 @@ compat/regex/regex.sp compat/regex/regex.o: EXTRA_CPPFLAGS = \
|
|||
-DGAWK -DNO_MBSUPPORT
|
||||
endif
|
||||
|
||||
ifdef USE_NED_ALLOCATOR
|
||||
compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \
|
||||
-DNDEBUG -DREPLACE_SYSTEM_ALLOCATOR
|
||||
compat/nedmalloc/nedmalloc.sp: SP_EXTRA_FLAGS += -Wno-non-pointer-null
|
||||
endif
|
||||
|
||||
headless-git.o: compat/win32/headless.c GIT-CFLAGS
|
||||
$(QUIET_CC)$(CC) $(ALL_CFLAGS) $(COMPAT_CFLAGS) \
|
||||
-fno-stack-protector -o $@ -c -Wall -Wwrite-strings $<
|
||||
|
|
|
|||
2
RelNotes
2
RelNotes
|
|
@ -1 +1 @@
|
|||
Documentation/RelNotes/2.54.0.adoc
|
||||
Documentation/RelNotes/2.55.0.adoc
|
||||
16
alias.c
16
alias.c
|
|
@ -34,8 +34,20 @@ static int config_alias_cb(const char *var, const char *value,
|
|||
if (subsection && !subsection_len)
|
||||
subsection = NULL;
|
||||
|
||||
if (subsection && strcmp(key, "command"))
|
||||
return 0;
|
||||
if (subsection && strcmp(key, "command")) {
|
||||
/*
|
||||
* We have historically supported the "alias.name" form when
|
||||
* "name" happens to contain dots (e.g., alias.foo.bar to allow
|
||||
* "git foo.bar". But our parsing above would split that into
|
||||
* subsection "foo".
|
||||
*
|
||||
* If we do not understand the final key in a subsection-style
|
||||
* variable, fall back to treating it as a two-level alias.
|
||||
*/
|
||||
key = var + strlen("alias.");
|
||||
subsection = NULL;
|
||||
subsection_len = 0;
|
||||
}
|
||||
|
||||
if (data->alias) {
|
||||
int match;
|
||||
|
|
|
|||
6
apply.c
6
apply.c
|
|
@ -4881,8 +4881,10 @@ static int apply_patch(struct apply_state *state,
|
|||
|
||||
state->patch_input_file = filename;
|
||||
state->linenr = 1;
|
||||
if (read_patch_file(&buf, fd) < 0)
|
||||
return -128;
|
||||
if (read_patch_file(&buf, fd) < 0) {
|
||||
res = -128;
|
||||
goto end;
|
||||
}
|
||||
offset = 0;
|
||||
while (offset < buf.len) {
|
||||
struct patch *patch;
|
||||
|
|
|
|||
|
|
@ -786,7 +786,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
|
|||
* die ourselves; but its error message will be more specific
|
||||
* than what we could write here.
|
||||
*/
|
||||
setup_git_directory();
|
||||
setup_git_directory(the_repository);
|
||||
}
|
||||
|
||||
parse_treeish_arg(argv, &args, remote);
|
||||
|
|
|
|||
2
blame.c
2
blame.c
|
|
@ -2813,7 +2813,7 @@ void setup_scoreboard(struct blame_scoreboard *sb,
|
|||
}
|
||||
|
||||
if (!sb->contents_from)
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
|
||||
sb->final = fake_working_tree_commit(sb->repo,
|
||||
&sb->revs->diffopt,
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix, struct re
|
|||
int cmd_for_each_ref(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
int cmd_for_each_repo(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
int cmd_format_patch(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
int cmd_format_rev(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
int cmd_fsck(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
int cmd_gc(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
|
|
@ -271,6 +272,7 @@ int cmd_update_server_info(int argc, const char **argv, const char *prefix, stru
|
|||
int cmd_upload_archive(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
int cmd_upload_pack(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
int cmd_url_parse(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
int cmd_var(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
int cmd_verify_commit(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
int cmd_verify_tag(int argc, const char **argv, const char *prefix, struct repository *repo);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "run-command.h"
|
||||
#include "object-file.h"
|
||||
#include "odb.h"
|
||||
#include "odb/transaction.h"
|
||||
#include "parse-options.h"
|
||||
#include "path.h"
|
||||
#include "preload-index.h"
|
||||
|
|
|
|||
|
|
@ -490,9 +490,11 @@ static int run_applypatch_msg_hook(struct am_state *state)
|
|||
|
||||
assert(state->msg);
|
||||
|
||||
if (!state->no_verify)
|
||||
ret = run_hooks_l(the_repository, "applypatch-msg",
|
||||
am_path(state, "final-commit"), NULL);
|
||||
if (!state->no_verify) {
|
||||
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT_FORCE_SERIAL;
|
||||
strvec_push(&opt.args, am_path(state, "final-commit"));
|
||||
ret = run_hooks_opt(the_repository, "applypatch-msg", &opt);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
FREE_AND_NULL(state->msg);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#include "path-walk.h"
|
||||
|
||||
static const char * const builtin_backfill_usage[] = {
|
||||
N_("git backfill [--min-batch-size=<n>] [--[no-]sparse]"),
|
||||
N_("git backfill [--min-batch-size=<n>] [--[no-]sparse] [--[no-]include-edges] [<revision-range>]"),
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -35,6 +35,7 @@ struct backfill_context {
|
|||
struct oid_array current_batch;
|
||||
size_t min_batch_size;
|
||||
int sparse;
|
||||
int include_edges;
|
||||
struct rev_info revs;
|
||||
};
|
||||
|
||||
|
|
@ -78,6 +79,28 @@ static int fill_missing_blobs(const char *path UNUSED,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void reject_unsupported_rev_list_options(struct rev_info *revs)
|
||||
{
|
||||
if (revs->diffopt.pickaxe)
|
||||
die(_("'%s' cannot be used with 'git backfill'"),
|
||||
(revs->diffopt.pickaxe_opts & DIFF_PICKAXE_REGEX) ? "-G" : "-S");
|
||||
if (revs->diffopt.filter || revs->diffopt.filter_not)
|
||||
die(_("'%s' cannot be used with 'git backfill'"),
|
||||
"--diff-filter");
|
||||
if (revs->diffopt.flags.follow_renames)
|
||||
die(_("'%s' cannot be used with 'git backfill'"),
|
||||
"--follow");
|
||||
if (revs->line_level_traverse)
|
||||
die(_("'%s' cannot be used with 'git backfill'"),
|
||||
"-L");
|
||||
if (revs->explicit_diff_merges)
|
||||
die(_("'%s' cannot be used with 'git backfill'"),
|
||||
"--diff-merges");
|
||||
if (revs->filter.choice)
|
||||
die(_("'%s' cannot be used with 'git backfill'"),
|
||||
"--filter");
|
||||
}
|
||||
|
||||
static int do_backfill(struct backfill_context *ctx)
|
||||
{
|
||||
struct path_walk_info info = PATH_WALK_INFO_INIT;
|
||||
|
|
@ -94,6 +117,8 @@ static int do_backfill(struct backfill_context *ctx)
|
|||
/* Walk from HEAD if otherwise unspecified. */
|
||||
if (!ctx->revs.pending.nr)
|
||||
add_head_to_pending(&ctx->revs);
|
||||
if (ctx->include_edges)
|
||||
ctx->revs.edge_hint = 1;
|
||||
|
||||
info.blobs = 1;
|
||||
info.tags = info.commits = info.trees = 0;
|
||||
|
|
@ -121,12 +146,15 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
|
|||
.min_batch_size = 50000,
|
||||
.sparse = -1,
|
||||
.revs = REV_INFO_INIT,
|
||||
.include_edges = 1,
|
||||
};
|
||||
struct option options[] = {
|
||||
OPT_UNSIGNED(0, "min-batch-size", &ctx.min_batch_size,
|
||||
N_("Minimum number of objects to request at a time")),
|
||||
OPT_BOOL(0, "sparse", &ctx.sparse,
|
||||
N_("Restrict the missing objects to the current sparse-checkout")),
|
||||
OPT_BOOL(0, "include-edges", &ctx.include_edges,
|
||||
N_("Include blobs from boundary commits in the backfill")),
|
||||
OPT_END(),
|
||||
};
|
||||
struct repo_config_values *cfg = repo_config_values(the_repository);
|
||||
|
|
@ -144,6 +172,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
|
|||
|
||||
if (argc > 1)
|
||||
die(_("unrecognized argument: %s"), argv[1]);
|
||||
reject_unsupported_rev_list_options(&ctx.revs);
|
||||
|
||||
repo_config(repo, git_default_config, NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -708,7 +708,7 @@ static unsigned parse_score(const char *arg)
|
|||
|
||||
static char *add_prefix(const char *prefix, const char *path)
|
||||
{
|
||||
return prefix_path(prefix, prefix ? strlen(prefix) : 0, path);
|
||||
return prefix_path(the_repository, prefix, prefix ? strlen(prefix) : 0, path);
|
||||
}
|
||||
|
||||
static int git_blame_config(const char *var, const char *value,
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ static void check_attr(const char *prefix, struct attr_check *check,
|
|||
|
||||
{
|
||||
char *full_path =
|
||||
prefix_path(prefix, prefix ? strlen(prefix) : 0, file);
|
||||
prefix_path(the_repository, prefix, prefix ? strlen(prefix) : 0, file);
|
||||
|
||||
if (collect_all) {
|
||||
git_all_attrs(the_repository->index, full_path, check);
|
||||
|
|
@ -117,7 +117,7 @@ int cmd_check_attr(int argc,
|
|||
int cnt, i, doubledash, filei;
|
||||
|
||||
if (!is_bare_repository())
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
|
||||
repo_config(the_repository, git_default_config, NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
/*
|
||||
* GIT - The information manager from hell
|
||||
*/
|
||||
|
||||
#define USE_THE_REPOSITORY_VARIABLE
|
||||
|
||||
#include "builtin.h"
|
||||
#include "refs.h"
|
||||
#include "setup.h"
|
||||
|
|
@ -41,7 +44,7 @@ static int check_ref_format_branch(const char *arg)
|
|||
const char *name;
|
||||
int nongit;
|
||||
|
||||
setup_git_directory_gently(&nongit);
|
||||
setup_git_directory_gently(the_repository, &nongit);
|
||||
if (check_branch_ref(&sb, arg) ||
|
||||
!skip_prefix(sb.buf, "refs/heads/", &name))
|
||||
die("'%s' is not a valid branch name", arg);
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ int cmd_checkout_index(int argc,
|
|||
die("git checkout-index: don't mix '--all' and explicit filenames");
|
||||
if (read_from_stdin)
|
||||
die("git checkout-index: don't mix '--stdin' and explicit filenames");
|
||||
p = prefix_path(prefix, prefix_length, arg);
|
||||
p = prefix_path(repo, prefix, prefix_length, arg);
|
||||
err |= checkout_file(repo->index, p, prefix);
|
||||
free(p);
|
||||
}
|
||||
|
|
@ -325,7 +325,7 @@ int cmd_checkout_index(int argc,
|
|||
die("line is badly quoted");
|
||||
strbuf_swap(&buf, &unquoted);
|
||||
}
|
||||
p = prefix_path(prefix, prefix_length, buf.buf);
|
||||
p = prefix_path(repo, prefix, prefix_length, buf.buf);
|
||||
err |= checkout_file(repo->index, p, prefix);
|
||||
free(p);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
#include "merge-ll.h"
|
||||
#include "lockfile.h"
|
||||
#include "mem-pool.h"
|
||||
#include "merge-ort-wrappers.h"
|
||||
#include "object-file.h"
|
||||
#include "object-name.h"
|
||||
#include "odb.h"
|
||||
|
|
@ -30,7 +29,9 @@
|
|||
#include "repo-settings.h"
|
||||
#include "resolve-undo.h"
|
||||
#include "revision.h"
|
||||
#include "sequencer.h"
|
||||
#include "setup.h"
|
||||
#include "strvec.h"
|
||||
#include "submodule.h"
|
||||
#include "symlinks.h"
|
||||
#include "trace2.h"
|
||||
|
|
@ -99,6 +100,8 @@ struct checkout_opts {
|
|||
.auto_advance = 1, \
|
||||
}
|
||||
|
||||
#define MERGE_WORKING_TREE_UNPACK_FAILED (-2)
|
||||
|
||||
struct branch_info {
|
||||
char *name; /* The short name used */
|
||||
char *path; /* The full name of a real branch */
|
||||
|
|
@ -123,13 +126,19 @@ static void branch_info_release(struct branch_info *info)
|
|||
static int post_checkout_hook(struct commit *old_commit, struct commit *new_commit,
|
||||
int changed)
|
||||
{
|
||||
return run_hooks_l(the_repository, "post-checkout",
|
||||
oid_to_hex(old_commit ? &old_commit->object.oid : null_oid(the_hash_algo)),
|
||||
oid_to_hex(new_commit ? &new_commit->object.oid : null_oid(the_hash_algo)),
|
||||
changed ? "1" : "0", NULL);
|
||||
/* "new_commit" can be NULL when checking out from the index before
|
||||
a commit exists. */
|
||||
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT_FORCE_SERIAL;
|
||||
|
||||
/*
|
||||
* "new_commit" can be NULL when checking out from the index before
|
||||
* a commit exists.
|
||||
*/
|
||||
strvec_pushl(&opt.args,
|
||||
oid_to_hex(old_commit ? &old_commit->object.oid : null_oid(the_hash_algo)),
|
||||
oid_to_hex(new_commit ? &new_commit->object.oid : null_oid(the_hash_algo)),
|
||||
changed ? "1" : "0",
|
||||
NULL);
|
||||
|
||||
return run_hooks_opt(the_repository, "post-checkout", &opt);
|
||||
}
|
||||
|
||||
static int update_some(const struct object_id *oid, struct strbuf *base,
|
||||
|
|
@ -753,9 +762,9 @@ static void setup_branch_path(struct branch_info *branch)
|
|||
branch->path = strbuf_detach(&buf, NULL);
|
||||
}
|
||||
|
||||
static void init_topts(struct unpack_trees_options *topts, int merge,
|
||||
static void init_topts(struct unpack_trees_options *topts,
|
||||
int show_progress, int overwrite_ignore,
|
||||
struct commit *old_commit)
|
||||
bool quiet)
|
||||
{
|
||||
memset(topts, 0, sizeof(*topts));
|
||||
topts->head_idx = -1;
|
||||
|
|
@ -767,7 +776,7 @@ static void init_topts(struct unpack_trees_options *topts, int merge,
|
|||
topts->initial_checkout = is_index_unborn(the_repository->index);
|
||||
topts->update = 1;
|
||||
topts->merge = 1;
|
||||
topts->quiet = merge && old_commit;
|
||||
topts->quiet = quiet;
|
||||
topts->verbose_update = show_progress;
|
||||
topts->fn = twoway_merge;
|
||||
topts->preserve_ignored = !overwrite_ignore;
|
||||
|
|
@ -776,6 +785,7 @@ static void init_topts(struct unpack_trees_options *topts, int merge,
|
|||
static int merge_working_tree(const struct checkout_opts *opts,
|
||||
struct branch_info *old_branch_info,
|
||||
struct branch_info *new_branch_info,
|
||||
bool quiet,
|
||||
int *writeout_error)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -783,8 +793,10 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
|||
struct tree *new_tree;
|
||||
|
||||
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
|
||||
if (repo_read_index_preload(the_repository, NULL, 0) < 0)
|
||||
if (repo_read_index_preload(the_repository, NULL, 0) < 0) {
|
||||
rollback_lock_file(&lock_file);
|
||||
return error(_("index file corrupt"));
|
||||
}
|
||||
|
||||
resolve_undo_clear_index(the_repository->index);
|
||||
if (opts->new_orphan_branch && opts->orphan_from_empty_tree) {
|
||||
|
|
@ -797,14 +809,18 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
|||
} else {
|
||||
new_tree = repo_get_commit_tree(the_repository,
|
||||
new_branch_info->commit);
|
||||
if (!new_tree)
|
||||
if (!new_tree) {
|
||||
rollback_lock_file(&lock_file);
|
||||
return error(_("unable to read tree (%s)"),
|
||||
oid_to_hex(&new_branch_info->commit->object.oid));
|
||||
}
|
||||
}
|
||||
if (opts->discard_changes) {
|
||||
ret = reset_tree(new_tree, opts, 1, writeout_error, new_branch_info);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
rollback_lock_file(&lock_file);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
struct tree_desc trees[2];
|
||||
struct tree *tree;
|
||||
|
|
@ -814,13 +830,14 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
|||
refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL, NULL);
|
||||
|
||||
if (unmerged_index(the_repository->index)) {
|
||||
rollback_lock_file(&lock_file);
|
||||
error(_("you need to resolve your current index first"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 2-way merge to the new branch */
|
||||
init_topts(&topts, opts->merge, opts->show_progress,
|
||||
opts->overwrite_ignore, old_branch_info->commit);
|
||||
init_topts(&topts, opts->show_progress,
|
||||
opts->overwrite_ignore, quiet);
|
||||
init_checkout_metadata(&topts.meta, new_branch_info->refname,
|
||||
new_branch_info->commit ?
|
||||
&new_branch_info->commit->object.oid :
|
||||
|
|
@ -846,82 +863,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
|||
ret = unpack_trees(2, trees, &topts);
|
||||
clear_unpack_trees_porcelain(&topts);
|
||||
if (ret == -1) {
|
||||
/*
|
||||
* Unpack couldn't do a trivial merge; either
|
||||
* give up or do a real merge, depending on
|
||||
* whether the merge flag was used.
|
||||
*/
|
||||
struct tree *work;
|
||||
struct tree *old_tree;
|
||||
struct merge_options o;
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
struct strbuf old_commit_shortname = STRBUF_INIT;
|
||||
|
||||
if (!opts->merge)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Without old_branch_info->commit, the below is the same as
|
||||
* the two-tree unpack we already tried and failed.
|
||||
*/
|
||||
if (!old_branch_info->commit)
|
||||
return 1;
|
||||
old_tree = repo_get_commit_tree(the_repository,
|
||||
old_branch_info->commit);
|
||||
|
||||
if (repo_index_has_changes(the_repository, old_tree, &sb))
|
||||
die(_("cannot continue with staged changes in "
|
||||
"the following files:\n%s"), sb.buf);
|
||||
strbuf_release(&sb);
|
||||
|
||||
/* Do more real merge */
|
||||
|
||||
/*
|
||||
* We update the index fully, then write the
|
||||
* tree from the index, then merge the new
|
||||
* branch with the current tree, with the old
|
||||
* branch as the base. Then we reset the index
|
||||
* (but not the working tree) to the new
|
||||
* branch, leaving the working tree as the
|
||||
* merged version, but skipping unmerged
|
||||
* entries in the index.
|
||||
*/
|
||||
|
||||
add_files_to_cache(the_repository, NULL, NULL, NULL, 0,
|
||||
0, 0);
|
||||
init_ui_merge_options(&o, the_repository);
|
||||
o.verbosity = 0;
|
||||
work = write_in_core_index_as_tree(the_repository,
|
||||
the_repository->index);
|
||||
|
||||
ret = reset_tree(new_tree,
|
||||
opts, 1,
|
||||
writeout_error, new_branch_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
o.ancestor = old_branch_info->name;
|
||||
if (!old_branch_info->name) {
|
||||
strbuf_add_unique_abbrev(&old_commit_shortname,
|
||||
&old_branch_info->commit->object.oid,
|
||||
DEFAULT_ABBREV);
|
||||
o.ancestor = old_commit_shortname.buf;
|
||||
}
|
||||
o.branch1 = new_branch_info->name;
|
||||
o.branch2 = "local";
|
||||
o.conflict_style = opts->conflict_style;
|
||||
ret = merge_ort_nonrecursive(&o,
|
||||
new_tree,
|
||||
work,
|
||||
old_tree);
|
||||
if (ret < 0)
|
||||
die(NULL);
|
||||
ret = reset_tree(new_tree,
|
||||
opts, 0,
|
||||
writeout_error, new_branch_info);
|
||||
strbuf_release(&o.obuf);
|
||||
strbuf_release(&old_commit_shortname);
|
||||
if (ret)
|
||||
return ret;
|
||||
rollback_lock_file(&lock_file);
|
||||
return MERGE_WORKING_TREE_UNPACK_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1166,6 +1109,10 @@ static int switch_branches(const struct checkout_opts *opts,
|
|||
struct object_id rev;
|
||||
int flag, writeout_error = 0;
|
||||
int do_merge = 1;
|
||||
int created_autostash = 0;
|
||||
struct strbuf old_commit_shortname = STRBUF_INIT;
|
||||
struct strbuf autostash_msg = STRBUF_INIT;
|
||||
const char *stash_label_base = NULL;
|
||||
|
||||
trace2_cmd_mode("branch");
|
||||
|
||||
|
|
@ -1203,11 +1150,49 @@ static int switch_branches(const struct checkout_opts *opts,
|
|||
do_merge = 0;
|
||||
}
|
||||
|
||||
if (old_branch_info.name) {
|
||||
stash_label_base = old_branch_info.name;
|
||||
} else if (old_branch_info.commit) {
|
||||
strbuf_add_unique_abbrev(&old_commit_shortname,
|
||||
&old_branch_info.commit->object.oid,
|
||||
DEFAULT_ABBREV);
|
||||
stash_label_base = old_commit_shortname.buf;
|
||||
}
|
||||
|
||||
if (do_merge) {
|
||||
ret = merge_working_tree(opts, &old_branch_info, new_branch_info, &writeout_error);
|
||||
ret = merge_working_tree(opts, &old_branch_info, new_branch_info,
|
||||
opts->merge, &writeout_error);
|
||||
if (ret == MERGE_WORKING_TREE_UNPACK_FAILED && opts->merge) {
|
||||
strbuf_addf(&autostash_msg,
|
||||
"autostash while switching to '%s'",
|
||||
new_branch_info->name);
|
||||
create_autostash_ref(the_repository,
|
||||
"CHECKOUT_AUTOSTASH_HEAD",
|
||||
autostash_msg.buf, true);
|
||||
created_autostash = 1;
|
||||
ret = merge_working_tree(opts, &old_branch_info, new_branch_info,
|
||||
false, &writeout_error);
|
||||
}
|
||||
if (created_autostash) {
|
||||
if (opts->conflict_style >= 0) {
|
||||
struct strbuf cfg = STRBUF_INIT;
|
||||
strbuf_addf(&cfg, "merge.conflictStyle=%s",
|
||||
conflict_style_name(opts->conflict_style));
|
||||
git_config_push_parameter(cfg.buf);
|
||||
strbuf_release(&cfg);
|
||||
}
|
||||
apply_autostash_ref(the_repository,
|
||||
"CHECKOUT_AUTOSTASH_HEAD",
|
||||
new_branch_info->name,
|
||||
"local",
|
||||
stash_label_base,
|
||||
autostash_msg.buf);
|
||||
}
|
||||
if (ret) {
|
||||
branch_info_release(&old_branch_info);
|
||||
return ret;
|
||||
strbuf_release(&old_commit_shortname);
|
||||
strbuf_release(&autostash_msg);
|
||||
return ret < 0 ? 1 : ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1216,8 +1201,22 @@ static int switch_branches(const struct checkout_opts *opts,
|
|||
|
||||
update_refs_for_switch(opts, &old_branch_info, new_branch_info);
|
||||
|
||||
if (created_autostash) {
|
||||
discard_index(the_repository->index);
|
||||
if (repo_read_index(the_repository) < 0)
|
||||
die(_("index file corrupt"));
|
||||
|
||||
if (!opts->quiet && new_branch_info->commit) {
|
||||
printf(_("The following paths have local changes:\n"));
|
||||
show_local_changes(&new_branch_info->commit->object,
|
||||
&opts->diff_options);
|
||||
}
|
||||
}
|
||||
|
||||
ret = post_checkout_hook(old_branch_info.commit, new_branch_info->commit, 1);
|
||||
branch_info_release(&old_branch_info);
|
||||
strbuf_release(&old_commit_shortname);
|
||||
strbuf_release(&autostash_msg);
|
||||
|
||||
return ret || writeout_error;
|
||||
}
|
||||
|
|
@ -1485,7 +1484,7 @@ static int parse_branchname_arg(int argc, const char **argv,
|
|||
* it would be extremely annoying.
|
||||
*/
|
||||
if (argc)
|
||||
verify_non_filename(opts->prefix, arg);
|
||||
verify_non_filename(the_repository, opts->prefix, arg);
|
||||
} else if (opts->accept_pathspec) {
|
||||
argcount++;
|
||||
argv++;
|
||||
|
|
|
|||
|
|
@ -647,6 +647,7 @@ static int checkout(int submodule_progress,
|
|||
struct tree *tree;
|
||||
struct tree_desc t;
|
||||
int err = 0;
|
||||
struct run_hooks_opt hook_opt = RUN_HOOKS_OPT_INIT_FORCE_SERIAL;
|
||||
|
||||
if (option_no_checkout)
|
||||
return 0;
|
||||
|
|
@ -668,7 +669,7 @@ static int checkout(int submodule_progress,
|
|||
}
|
||||
|
||||
/* We need to be in the new work tree for the checkout */
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
|
||||
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
|
||||
|
||||
|
|
@ -697,8 +698,9 @@ static int checkout(int submodule_progress,
|
|||
if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
|
||||
die(_("unable to write new index file"));
|
||||
|
||||
err |= run_hooks_l(the_repository, "post-checkout", oid_to_hex(null_oid(the_hash_algo)),
|
||||
oid_to_hex(&oid), "1", NULL);
|
||||
strvec_pushl(&hook_opt.args, oid_to_hex(null_oid(the_hash_algo)),
|
||||
oid_to_hex(&oid), "1", NULL);
|
||||
err |= run_hooks_opt(the_repository, "post-checkout", &hook_opt);
|
||||
|
||||
if (!err && (option_recurse_submodules.nr > 0)) {
|
||||
struct child_process cmd = CHILD_PROCESS_INIT;
|
||||
|
|
@ -1114,7 +1116,7 @@ int cmd_clone(int argc,
|
|||
die_errno(_("could not create work tree dir '%s'"),
|
||||
work_tree);
|
||||
junk_work_tree = work_tree;
|
||||
set_git_work_tree(work_tree);
|
||||
set_git_work_tree(the_repository, work_tree);
|
||||
}
|
||||
|
||||
if (real_git_dir) {
|
||||
|
|
@ -1184,7 +1186,7 @@ int cmd_clone(int argc,
|
|||
* 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(the_repository, git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN,
|
||||
ref_storage_format, NULL,
|
||||
do_not_override_repo_unix_permissions, INIT_DB_QUIET | INIT_DB_SKIP_REFDB);
|
||||
|
||||
|
|
@ -1227,7 +1229,7 @@ int cmd_clone(int argc,
|
|||
*
|
||||
* This is sufficient for Git commands to discover the Git directory.
|
||||
*/
|
||||
initialize_repository_version(GIT_HASH_UNKNOWN,
|
||||
initialize_repository_version(the_repository, GIT_HASH_UNKNOWN,
|
||||
the_repository->ref_storage_format, 1);
|
||||
|
||||
refs_create_refdir_stubs(the_repository, git_dir, NULL);
|
||||
|
|
@ -1440,9 +1442,9 @@ int cmd_clone(int argc,
|
|||
* ours to the same thing.
|
||||
*/
|
||||
hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
|
||||
initialize_repository_version(hash_algo, the_repository->ref_storage_format, 1);
|
||||
initialize_repository_version(the_repository, hash_algo, the_repository->ref_storage_format, 1);
|
||||
repo_set_hash_algo(the_repository, hash_algo);
|
||||
create_reference_database(NULL, 1);
|
||||
create_reference_database(the_repository, NULL, 1);
|
||||
|
||||
/*
|
||||
* Before fetching from the remote, download and install bundle
|
||||
|
|
|
|||
|
|
@ -1979,7 +1979,8 @@ int cmd_commit(int argc,
|
|||
&oid, flags);
|
||||
}
|
||||
|
||||
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
|
||||
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH",
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
cleanup:
|
||||
free_commit_extra_headers(extra);
|
||||
|
|
|
|||
|
|
@ -781,7 +781,7 @@ int cmd_describe(int argc,
|
|||
struct rev_info revs;
|
||||
int fd;
|
||||
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
prepare_repo_settings(the_repository);
|
||||
the_repository->settings.command_requires_full_index = 0;
|
||||
repo_read_index(the_repository);
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ int cmd_diff_index(int argc,
|
|||
rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1)
|
||||
usage(diff_cache_usage);
|
||||
if (!(option & DIFF_INDEX_CACHED)) {
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
if (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0) {
|
||||
perror("repo_read_index_preload");
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ static void builtin_diff_index(struct rev_info *revs,
|
|||
revs->max_age != -1)
|
||||
usage(builtin_diff_usage);
|
||||
if (!(option & DIFF_INDEX_CACHED)) {
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
if (repo_read_index_preload(the_repository,
|
||||
&revs->diffopt.pathspec, 0) < 0) {
|
||||
die_errno("repo_read_index_preload");
|
||||
|
|
@ -281,7 +281,7 @@ static void builtin_diff_files(struct rev_info *revs, int argc, const char **arg
|
|||
(revs->diffopt.output_format & DIFF_FORMAT_PATCH))
|
||||
diff_merges_set_dense_combined_if_unset(revs);
|
||||
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
if (repo_read_index_preload(the_repository, &revs->diffopt.pathspec,
|
||||
0) < 0) {
|
||||
die_errno("repo_read_index_preload");
|
||||
|
|
@ -455,7 +455,7 @@ int cmd_diff(int argc,
|
|||
break;
|
||||
}
|
||||
|
||||
prefix = setup_git_directory_gently(&nongit);
|
||||
prefix = setup_git_directory_gently(the_repository, &nongit);
|
||||
|
||||
if (!nongit) {
|
||||
prepare_repo_settings(the_repository);
|
||||
|
|
@ -471,8 +471,8 @@ int cmd_diff(int argc,
|
|||
* as a colourful "diff" replacement.
|
||||
*/
|
||||
if (nongit || ((argc == i + 2) &&
|
||||
(!path_inside_repo(prefix, argv[i]) ||
|
||||
!path_inside_repo(prefix, argv[i + 1]))))
|
||||
(!path_inside_repo(the_repository, prefix, argv[i]) ||
|
||||
!path_inside_repo(the_repository, prefix, argv[i + 1]))))
|
||||
no_index = DIFF_NO_INDEX_IMPLICIT;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -767,7 +767,7 @@ int cmd_difftool(int argc,
|
|||
die(_("difftool requires worktree or --no-index"));
|
||||
|
||||
if (!no_index){
|
||||
setup_work_tree();
|
||||
setup_work_tree(repo);
|
||||
setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(repo)), 1);
|
||||
setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(repo)), 1);
|
||||
} else if (dir_diff)
|
||||
|
|
|
|||
|
|
@ -98,7 +98,8 @@ static struct transport *gtransport;
|
|||
static struct transport *gsecondary;
|
||||
static struct refspec refmap = REFSPEC_INIT_FETCH;
|
||||
static struct string_list server_options = STRING_LIST_INIT_DUP;
|
||||
static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP;
|
||||
static struct string_list negotiation_restrict = STRING_LIST_INIT_NODUP;
|
||||
static struct string_list negotiation_include = STRING_LIST_INIT_NODUP;
|
||||
|
||||
struct fetch_config {
|
||||
enum display_format display_format;
|
||||
|
|
@ -1534,23 +1535,29 @@ static int add_oid(const struct reference *ref, void *cb_data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void add_negotiation_tips(struct git_transport_options *smart_options)
|
||||
static void add_negotiation_tips(struct string_list *input_list,
|
||||
struct oid_array **output_list,
|
||||
const char *argname)
|
||||
{
|
||||
struct oid_array *oids = xcalloc(1, sizeof(*oids));
|
||||
int i;
|
||||
|
||||
for (i = 0; i < negotiation_tip.nr; i++) {
|
||||
const char *s = negotiation_tip.items[i].string;
|
||||
for (i = 0; i < input_list->nr; i++) {
|
||||
const char *s = input_list->items[i].string;
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.pattern = s,
|
||||
};
|
||||
int old_nr;
|
||||
if (!has_glob_specials(s)) {
|
||||
struct object_id oid;
|
||||
|
||||
/* Ignore missing reference. */
|
||||
if (repo_get_oid(the_repository, s, &oid))
|
||||
die(_("%s is not a valid object"), s);
|
||||
continue;
|
||||
/* Fail on missing object pointed by ref. */
|
||||
if (!odb_has_object(the_repository->objects, &oid, 0))
|
||||
die(_("the object %s does not exist"), s);
|
||||
|
||||
oid_array_append(oids, &oid);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1558,10 +1565,10 @@ static void add_negotiation_tips(struct git_transport_options *smart_options)
|
|||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
add_oid, oids, &opts);
|
||||
if (old_nr == oids->nr)
|
||||
warning("ignoring --negotiation-tip=%s because it does not match any refs",
|
||||
s);
|
||||
warning(_("ignoring %s=%s because it does not match any refs"),
|
||||
argname, s);
|
||||
}
|
||||
smart_options->negotiation_tips = oids;
|
||||
*output_list = oids;
|
||||
}
|
||||
|
||||
static struct transport *prepare_transport(struct remote *remote, int deepen,
|
||||
|
|
@ -1595,11 +1602,50 @@ static struct transport *prepare_transport(struct remote *remote, int deepen,
|
|||
set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER, spec);
|
||||
set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
|
||||
}
|
||||
if (negotiation_tip.nr) {
|
||||
if (negotiation_restrict.nr) {
|
||||
if (transport->smart_options)
|
||||
add_negotiation_tips(transport->smart_options);
|
||||
add_negotiation_tips(&negotiation_restrict,
|
||||
&transport->smart_options->negotiation_restrict_tips,
|
||||
"--negotiation-restrict");
|
||||
else
|
||||
warning("ignoring --negotiation-tip because the protocol does not support it");
|
||||
warning(_("ignoring %s because the protocol does not support it"),
|
||||
"--negotiation-restrict");
|
||||
} else if (remote->negotiation_restrict.nr) {
|
||||
struct string_list_item *item;
|
||||
for_each_string_list_item(item, &remote->negotiation_restrict)
|
||||
string_list_append(&negotiation_restrict, item->string);
|
||||
if (transport->smart_options)
|
||||
add_negotiation_tips(&negotiation_restrict,
|
||||
&transport->smart_options->negotiation_restrict_tips,
|
||||
"--negotiation-restrict");
|
||||
else {
|
||||
struct strbuf config_name = STRBUF_INIT;
|
||||
strbuf_addf(&config_name, "remote.%s.negotiationRestrict", remote->name);
|
||||
warning(_("ignoring %s because the protocol does not support it"),
|
||||
config_name.buf);
|
||||
strbuf_release(&config_name);
|
||||
}
|
||||
}
|
||||
if (negotiation_include.nr) {
|
||||
if (transport->smart_options)
|
||||
add_negotiation_tips(&negotiation_include,
|
||||
&transport->smart_options->negotiation_include_tips,
|
||||
"--negotiation-include");
|
||||
else
|
||||
warning(_("ignoring %s because the protocol does not support it"),
|
||||
"--negotiation-include");
|
||||
} else if (remote->negotiation_include.nr) {
|
||||
if (transport->smart_options) {
|
||||
add_negotiation_tips(&remote->negotiation_include,
|
||||
&transport->smart_options->negotiation_include_tips,
|
||||
"--negotiation-include");
|
||||
} else {
|
||||
struct strbuf config_name = STRBUF_INIT;
|
||||
strbuf_addf(&config_name, "remote.%s.negotiationInclude", remote->name);
|
||||
warning(_("ignoring %s because the protocol does not support it"),
|
||||
config_name.buf);
|
||||
strbuf_release(&config_name);
|
||||
}
|
||||
}
|
||||
return transport;
|
||||
}
|
||||
|
|
@ -2565,8 +2611,11 @@ int cmd_fetch(int argc,
|
|||
N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg),
|
||||
OPT_STRING_LIST('o', "server-option", &server_options, N_("server-specific"), N_("option to transmit")),
|
||||
OPT_IPVERSION(&family),
|
||||
OPT_STRING_LIST(0, "negotiation-tip", &negotiation_tip, N_("revision"),
|
||||
OPT_STRING_LIST(0, "negotiation-restrict", &negotiation_restrict, N_("revision"),
|
||||
N_("report that we have only objects reachable from this object")),
|
||||
OPT_ALIAS(0, "negotiation-tip", "negotiation-restrict"),
|
||||
OPT_STRING_LIST(0, "negotiation-include", &negotiation_include, N_("revision"),
|
||||
N_("ensure this ref is always sent as a negotiation have")),
|
||||
OPT_BOOL(0, "negotiate-only", &negotiate_only,
|
||||
N_("do not fetch a packfile; instead, print ancestors of negotiation tips")),
|
||||
OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
|
||||
|
|
@ -2656,9 +2705,6 @@ int cmd_fetch(int argc,
|
|||
config.display_format = DISPLAY_FORMAT_PORCELAIN;
|
||||
}
|
||||
|
||||
if (negotiate_only && !negotiation_tip.nr)
|
||||
die(_("--negotiate-only needs one or more --negotiation-tip=*"));
|
||||
|
||||
if (deepen_relative) {
|
||||
if (deepen_relative < 0)
|
||||
die(_("negative depth in --deepen is not supported"));
|
||||
|
|
@ -2746,14 +2792,19 @@ int cmd_fetch(int argc,
|
|||
if (!remote)
|
||||
die(_("must supply remote when using --negotiate-only"));
|
||||
gtransport = prepare_transport(remote, 1, &filter_options);
|
||||
if (gtransport->smart_options) {
|
||||
gtransport->smart_options->acked_commits = &acked_commits;
|
||||
} else {
|
||||
|
||||
if (!gtransport->smart_options) {
|
||||
warning(_("protocol does not support --negotiate-only, exiting"));
|
||||
result = 1;
|
||||
trace2_region_leave("fetch", "negotiate-only", the_repository);
|
||||
goto cleanup;
|
||||
}
|
||||
if (!gtransport->smart_options->negotiation_restrict_tips)
|
||||
die(_("%s needs one or more %s"), "--negotiate-only",
|
||||
"--negotiation-restrict=*");
|
||||
|
||||
gtransport->smart_options->acked_commits = &acked_commits;
|
||||
|
||||
if (server_options.nr)
|
||||
gtransport->server_options = &server_options;
|
||||
result = transport_fetch_refs(gtransport, NULL);
|
||||
|
|
|
|||
|
|
@ -1590,6 +1590,7 @@ static int maintenance_task_geometric_repack(struct maintenance_run_opts *opts,
|
|||
pack_geometry_split(&geometry);
|
||||
|
||||
child.git_cmd = 1;
|
||||
child.odb_to_close = the_repository->objects;
|
||||
|
||||
strvec_pushl(&child.args, "repack", "-d", "-l", NULL);
|
||||
if (geometry.split < geometry.pack_nr)
|
||||
|
|
|
|||
151
builtin/grep.c
151
builtin/grep.c
|
|
@ -28,9 +28,12 @@
|
|||
#include "object-file.h"
|
||||
#include "object-name.h"
|
||||
#include "odb.h"
|
||||
#include "oid-array.h"
|
||||
#include "oidset.h"
|
||||
#include "packfile.h"
|
||||
#include "pager.h"
|
||||
#include "path.h"
|
||||
#include "promisor-remote.h"
|
||||
#include "read-cache-ll.h"
|
||||
#include "write-or-die.h"
|
||||
|
||||
|
|
@ -692,6 +695,144 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||
return hit;
|
||||
}
|
||||
|
||||
static void collect_blob_oids_for_tree(struct repository *repo,
|
||||
const struct pathspec *pathspec,
|
||||
struct tree_desc *tree,
|
||||
struct strbuf *base,
|
||||
int tn_len,
|
||||
struct oidset *blob_oids)
|
||||
{
|
||||
struct name_entry entry;
|
||||
int old_baselen = base->len;
|
||||
struct strbuf name = STRBUF_INIT;
|
||||
enum interesting match = entry_not_interesting;
|
||||
|
||||
while (tree_entry(tree, &entry)) {
|
||||
if (match != all_entries_interesting) {
|
||||
strbuf_addstr(&name, base->buf + tn_len);
|
||||
match = tree_entry_interesting(repo->index,
|
||||
&entry, &name,
|
||||
pathspec);
|
||||
strbuf_reset(&name);
|
||||
|
||||
if (match == all_entries_not_interesting)
|
||||
break;
|
||||
if (match == entry_not_interesting)
|
||||
continue;
|
||||
}
|
||||
|
||||
strbuf_add(base, entry.path, tree_entry_len(&entry));
|
||||
|
||||
if (S_ISREG(entry.mode)) {
|
||||
if (!odb_has_object(repo->objects, &entry.oid, 0))
|
||||
oidset_insert(blob_oids, &entry.oid);
|
||||
} else if (S_ISDIR(entry.mode)) {
|
||||
enum object_type type;
|
||||
struct tree_desc sub_tree;
|
||||
void *data;
|
||||
unsigned long size;
|
||||
|
||||
data = odb_read_object(repo->objects, &entry.oid,
|
||||
&type, &size);
|
||||
if (!data)
|
||||
die(_("unable to read tree (%s)"),
|
||||
oid_to_hex(&entry.oid));
|
||||
|
||||
strbuf_addch(base, '/');
|
||||
init_tree_desc(&sub_tree, &entry.oid, data, size);
|
||||
collect_blob_oids_for_tree(repo, pathspec, &sub_tree,
|
||||
base, tn_len, blob_oids);
|
||||
free(data);
|
||||
}
|
||||
/*
|
||||
* ...no else clause for S_ISGITLINK: submodules have their
|
||||
* own promisor configuration and would need separate fetches
|
||||
* anyway.
|
||||
*/
|
||||
|
||||
strbuf_setlen(base, old_baselen);
|
||||
}
|
||||
|
||||
strbuf_release(&name);
|
||||
}
|
||||
|
||||
static void collect_blob_oids_for_treeish(struct grep_opt *opt,
|
||||
const struct pathspec *pathspec,
|
||||
const struct object_id *tree_ish_oid,
|
||||
const char *name,
|
||||
struct oidset *blob_oids)
|
||||
{
|
||||
struct tree_desc tree;
|
||||
void *data;
|
||||
unsigned long size;
|
||||
struct strbuf base = STRBUF_INIT;
|
||||
int len;
|
||||
|
||||
data = odb_read_object_peeled(opt->repo->objects, tree_ish_oid,
|
||||
OBJ_TREE, &size, NULL);
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
len = name ? strlen(name) : 0;
|
||||
if (len) {
|
||||
strbuf_add(&base, name, len);
|
||||
strbuf_addch(&base, ':');
|
||||
}
|
||||
init_tree_desc(&tree, tree_ish_oid, data, size);
|
||||
|
||||
collect_blob_oids_for_tree(opt->repo, pathspec, &tree,
|
||||
&base, base.len, blob_oids);
|
||||
|
||||
strbuf_release(&base);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void prefetch_grep_blobs(struct grep_opt *opt,
|
||||
const struct pathspec *pathspec,
|
||||
const struct object_array *list)
|
||||
{
|
||||
struct oidset blob_oids = OIDSET_INIT;
|
||||
|
||||
/* Exit if we're not in a partial clone */
|
||||
if (!repo_has_promisor_remote(opt->repo))
|
||||
return;
|
||||
|
||||
/* For each tree, gather the blobs in it */
|
||||
for (int i = 0; i < list->nr; i++) {
|
||||
struct object *real_obj;
|
||||
|
||||
obj_read_lock();
|
||||
real_obj = deref_tag(opt->repo, list->objects[i].item,
|
||||
NULL, 0);
|
||||
obj_read_unlock();
|
||||
|
||||
if (real_obj &&
|
||||
(real_obj->type == OBJ_COMMIT ||
|
||||
real_obj->type == OBJ_TREE))
|
||||
collect_blob_oids_for_treeish(opt, pathspec,
|
||||
&real_obj->oid,
|
||||
list->objects[i].name,
|
||||
&blob_oids);
|
||||
}
|
||||
|
||||
/* Prefetch the blobs we found */
|
||||
if (oidset_size(&blob_oids)) {
|
||||
struct oid_array to_fetch = OID_ARRAY_INIT;
|
||||
struct oidset_iter iter;
|
||||
const struct object_id *oid;
|
||||
|
||||
oidset_iter_init(&blob_oids, &iter);
|
||||
while ((oid = oidset_iter_next(&iter)))
|
||||
oid_array_append(&to_fetch, oid);
|
||||
|
||||
promisor_remote_get_direct(opt->repo, to_fetch.oid, to_fetch.nr);
|
||||
|
||||
oid_array_clear(&to_fetch);
|
||||
}
|
||||
oidset_clear(&blob_oids);
|
||||
}
|
||||
|
||||
static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
|
||||
struct object *obj, const char *name, const char *path)
|
||||
{
|
||||
|
|
@ -732,6 +873,8 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||
int hit = 0;
|
||||
const unsigned int nr = list->nr;
|
||||
|
||||
prefetch_grep_blobs(opt, pathspec, list);
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
struct object *real_obj;
|
||||
|
||||
|
|
@ -1064,7 +1207,7 @@ int cmd_grep(int argc,
|
|||
use_index = 0;
|
||||
else
|
||||
/* die the same way as if we did it at the beginning */
|
||||
setup_git_directory();
|
||||
setup_git_directory(the_repository);
|
||||
}
|
||||
/* Ignore --recurse-submodules if --no-index is given or implied */
|
||||
if (!use_index)
|
||||
|
|
@ -1151,7 +1294,7 @@ int cmd_grep(int argc,
|
|||
|
||||
object = parse_object_or_die(the_repository, &oid, arg);
|
||||
if (!seen_dashdash)
|
||||
verify_non_filename(prefix, arg);
|
||||
verify_non_filename(the_repository, prefix, arg);
|
||||
add_object_array_with_path(object, arg, &list, oc.mode, oc.path);
|
||||
object_context_release(&oc);
|
||||
}
|
||||
|
|
@ -1163,7 +1306,7 @@ int cmd_grep(int argc,
|
|||
if (!seen_dashdash) {
|
||||
int j;
|
||||
for (j = i; j < argc; j++)
|
||||
verify_filename(prefix, argv[j], j == i && allow_revs);
|
||||
verify_filename(the_repository, prefix, argv[j], j == i && allow_revs);
|
||||
}
|
||||
|
||||
parse_pathspec(&pathspec, 0,
|
||||
|
|
@ -1272,7 +1415,7 @@ int cmd_grep(int argc,
|
|||
die(_("--[no-]exclude-standard cannot be used for tracked contents"));
|
||||
} else if (!list.nr) {
|
||||
if (!cached)
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
|
||||
hit = grep_cache(&opt, &pathspec, cached);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -100,9 +100,9 @@ int cmd_hash_object(int argc,
|
|||
hash_object_usage, 0);
|
||||
|
||||
if (flags & INDEX_WRITE_OBJECT)
|
||||
prefix = setup_git_directory();
|
||||
prefix = setup_git_directory(the_repository);
|
||||
else
|
||||
prefix = setup_git_directory_gently(&nongit);
|
||||
prefix = setup_git_directory_gently(the_repository, &nongit);
|
||||
|
||||
if (nongit && !the_hash_algo)
|
||||
repo_set_hash_algo(the_repository, GIT_HASH_DEFAULT);
|
||||
|
|
|
|||
|
|
@ -740,7 +740,7 @@ int cmd_help(int argc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
setup_git_directory_gently(&nongit);
|
||||
setup_git_directory_gently(the_repository, &nongit);
|
||||
repo_config(the_repository, git_help_config, NULL);
|
||||
|
||||
if (parsed_help_format != HELP_FORMAT_NONE)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "gettext.h"
|
||||
#include "hex.h"
|
||||
#include "lockfile.h"
|
||||
#include "merge-ort.h"
|
||||
#include "oidmap.h"
|
||||
#include "parse-options.h"
|
||||
#include "path.h"
|
||||
|
|
@ -23,6 +24,8 @@
|
|||
#include "unpack-trees.h"
|
||||
#include "wt-status.h"
|
||||
|
||||
#define GIT_HISTORY_FIXUP_USAGE \
|
||||
N_("git history fixup <commit> [--dry-run] [--update-refs=(branches|head)] [--reedit-message] [--empty=(drop|keep|abort)]")
|
||||
#define GIT_HISTORY_REWORD_USAGE \
|
||||
N_("git history reword <commit> [--dry-run] [--update-refs=(branches|head)]")
|
||||
#define GIT_HISTORY_SPLIT_USAGE \
|
||||
|
|
@ -91,13 +94,18 @@ static int fill_commit_message(struct repository *repo,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int commit_tree_with_edited_message_ext(struct repository *repo,
|
||||
const char *action,
|
||||
struct commit *commit_with_message,
|
||||
const struct commit_list *parents,
|
||||
const struct object_id *old_tree,
|
||||
const struct object_id *new_tree,
|
||||
struct commit **out)
|
||||
enum commit_tree_flags {
|
||||
COMMIT_TREE_EDIT_MESSAGE = (1 << 0),
|
||||
};
|
||||
|
||||
static int commit_tree_ext(struct repository *repo,
|
||||
const char *action,
|
||||
struct commit *commit_with_message,
|
||||
const struct commit_list *parents,
|
||||
const struct object_id *old_tree,
|
||||
const struct object_id *new_tree,
|
||||
struct commit **out,
|
||||
enum commit_tree_flags flags)
|
||||
{
|
||||
const char *exclude_gpgsig[] = {
|
||||
/* We reencode the message, so the encoding needs to be stripped. */
|
||||
|
|
@ -122,10 +130,14 @@ static int commit_tree_with_edited_message_ext(struct repository *repo,
|
|||
original_author = xmemdupz(ptr, len);
|
||||
find_commit_subject(original_message, &original_body);
|
||||
|
||||
ret = fill_commit_message(repo, old_tree, new_tree,
|
||||
original_body, action, &commit_message);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (flags & COMMIT_TREE_EDIT_MESSAGE) {
|
||||
ret = fill_commit_message(repo, old_tree, new_tree,
|
||||
original_body, action, &commit_message);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
} else {
|
||||
strbuf_addstr(&commit_message, original_body);
|
||||
}
|
||||
|
||||
original_extra_headers = read_commit_extra_headers(commit_with_message,
|
||||
exclude_gpgsig);
|
||||
|
|
@ -168,8 +180,8 @@ static int commit_tree_with_edited_message(struct repository *repo,
|
|||
oidcpy(&parent_tree_oid, repo->hash_algo->empty_tree);
|
||||
}
|
||||
|
||||
return commit_tree_with_edited_message_ext(repo, action, original, original->parents,
|
||||
&parent_tree_oid, tree_oid, out);
|
||||
return commit_tree_ext(repo, action, original, original->parents,
|
||||
&parent_tree_oid, tree_oid, out, COMMIT_TREE_EDIT_MESSAGE);
|
||||
}
|
||||
|
||||
enum ref_action {
|
||||
|
|
@ -326,10 +338,13 @@ static int handle_reference_updates(struct rev_info *revs,
|
|||
struct commit *original,
|
||||
struct commit *rewritten,
|
||||
const char *reflog_msg,
|
||||
int dry_run)
|
||||
int dry_run,
|
||||
enum replay_empty_commit_action empty)
|
||||
{
|
||||
const struct name_decoration *decoration;
|
||||
struct replay_revisions_options opts = { 0 };
|
||||
struct replay_revisions_options opts = {
|
||||
.empty = empty,
|
||||
};
|
||||
struct replay_result result = { 0 };
|
||||
struct ref_transaction *transaction = NULL;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
|
|
@ -425,6 +440,236 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int commit_became_empty(struct repository *repo,
|
||||
struct commit *original,
|
||||
struct tree *result)
|
||||
{
|
||||
struct commit *parent = original->parents ? original->parents->item : NULL;
|
||||
struct object_id parent_tree_oid;
|
||||
|
||||
if (parent) {
|
||||
if (repo_parse_commit(repo, parent))
|
||||
return error(_("unable to parse parent of %s"),
|
||||
oid_to_hex(&original->object.oid));
|
||||
|
||||
parent_tree_oid = repo_get_commit_tree(repo, parent)->object.oid;
|
||||
} else {
|
||||
oidcpy(&parent_tree_oid, repo->hash_algo->empty_tree);
|
||||
}
|
||||
|
||||
return oideq(&result->object.oid, &parent_tree_oid);
|
||||
}
|
||||
|
||||
static int parse_opt_empty(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
enum replay_empty_commit_action *value = opt->value;
|
||||
|
||||
BUG_ON_OPT_NEG(unset);
|
||||
|
||||
if (!strcmp(arg, "drop"))
|
||||
*value = REPLAY_EMPTY_COMMIT_DROP;
|
||||
else if (!strcmp(arg, "keep"))
|
||||
*value = REPLAY_EMPTY_COMMIT_KEEP;
|
||||
else if (!strcmp(arg, "abort"))
|
||||
*value = REPLAY_EMPTY_COMMIT_ABORT;
|
||||
else
|
||||
die(_("unrecognized '--empty=' action '%s'; "
|
||||
"valid values are \"drop\", \"keep\", and \"abort\"."), arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_history_fixup(int argc,
|
||||
const char **argv,
|
||||
const char *prefix,
|
||||
struct repository *repo)
|
||||
{
|
||||
const char * const usage[] = {
|
||||
GIT_HISTORY_FIXUP_USAGE,
|
||||
NULL,
|
||||
};
|
||||
enum replay_empty_commit_action empty = REPLAY_EMPTY_COMMIT_DROP;
|
||||
enum ref_action action = REF_ACTION_DEFAULT;
|
||||
enum commit_tree_flags flags = 0;
|
||||
int dry_run = 0;
|
||||
struct option options[] = {
|
||||
OPT_CALLBACK_F(0, "update-refs", &action, "(branches|head)",
|
||||
N_("control which refs should be updated"),
|
||||
PARSE_OPT_NONEG, parse_ref_action),
|
||||
OPT_BOOL('n', "dry-run", &dry_run,
|
||||
N_("perform a dry-run without updating any refs")),
|
||||
OPT_BIT(0, "reedit-message", &flags,
|
||||
N_("open an editor to modify the commit message"),
|
||||
COMMIT_TREE_EDIT_MESSAGE),
|
||||
OPT_CALLBACK_F(0, "empty", &empty, "(drop|keep|abort)",
|
||||
N_("how to handle commits that become empty"),
|
||||
PARSE_OPT_NONEG, parse_opt_empty),
|
||||
OPT_END(),
|
||||
};
|
||||
struct merge_result merge_result = { 0 };
|
||||
struct merge_options merge_opts = { 0 };
|
||||
struct strbuf reflog_msg = STRBUF_INIT;
|
||||
struct commit *head_commit, *original, *rewritten;
|
||||
struct tree *head_tree, *original_tree, *index_tree;
|
||||
struct rev_info revs = { 0 };
|
||||
bool skip_commit = false;
|
||||
int ret;
|
||||
|
||||
argc = parse_options(argc, argv, prefix, options, usage, 0);
|
||||
if (argc != 1) {
|
||||
ret = error(_("command expects a single revision"));
|
||||
goto out;
|
||||
}
|
||||
repo_config(repo, git_default_config, NULL);
|
||||
|
||||
if (action == REF_ACTION_DEFAULT)
|
||||
action = REF_ACTION_BRANCHES;
|
||||
|
||||
if (is_bare_repository()) {
|
||||
ret = error(_("cannot run fixup in a bare repository"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Resolve the original commit, which is the one we want to fix up. */
|
||||
original = lookup_commit_reference_by_name(argv[0]);
|
||||
if (!original) {
|
||||
ret = error(_("commit cannot be found: %s"), argv[0]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve HEAD so we can use its tree as the merge base: the staged
|
||||
* changes are expressed as a diff from HEAD's tree to the index tree.
|
||||
*/
|
||||
head_commit = lookup_commit_reference_by_name("HEAD");
|
||||
if (!head_commit) {
|
||||
ret = error(_("cannot look up HEAD"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
head_tree = repo_get_commit_tree(repo, head_commit);
|
||||
if (!head_tree) {
|
||||
ret = error(_("cannot get tree for HEAD"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (repo_read_index(repo) < 0) {
|
||||
ret = error(_("unable to read index"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!repo_index_has_changes(repo, head_tree, NULL)) {
|
||||
ret = error(_("nothing to fixup: no staged changes"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the index as a tree object. This is the "theirs" side of the
|
||||
* three-way merge: it is HEAD's tree with the staged changes applied.
|
||||
*/
|
||||
index_tree = write_in_core_index_as_tree(repo, repo->index);
|
||||
if (!index_tree) {
|
||||
ret = error(_("unable to write index as a tree"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
original_tree = repo_get_commit_tree(repo, original);
|
||||
if (!original_tree) {
|
||||
ret = error(_("cannot get tree for commit %s"), argv[0]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the three-way merge to reapply changes in the index onto the
|
||||
* target commit. This is using basically the same logic as a
|
||||
* cherry-pick, where the base commit is our HEAD, ours is the original
|
||||
* tree and theirs is the index tree.
|
||||
*/
|
||||
init_basic_merge_options(&merge_opts, repo);
|
||||
merge_opts.ancestor = "HEAD";
|
||||
merge_opts.branch1 = argv[0];
|
||||
merge_opts.branch2 = "staged";
|
||||
merge_incore_nonrecursive(&merge_opts, head_tree,
|
||||
original_tree, index_tree, &merge_result);
|
||||
|
||||
if (merge_result.clean < 0) {
|
||||
ret = error(_("merge failed while applying fixup"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!merge_result.clean) {
|
||||
ret = error(_("fixup would produce conflicts; aborting"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = commit_became_empty(repo, original, merge_result.tree);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (ret > 0) {
|
||||
switch (empty) {
|
||||
case REPLAY_EMPTY_COMMIT_DROP:
|
||||
/*
|
||||
* Drop the target commit by replaying its descendants
|
||||
* directly onto its parent.
|
||||
*/
|
||||
rewritten = original->parents ? original->parents->item : NULL;
|
||||
|
||||
/*
|
||||
* TODO: we don't yet have the ability to drop root
|
||||
* commits, but there's ultimately no good reason for
|
||||
* this restriction to exist other than a technical
|
||||
* limitation.
|
||||
*/
|
||||
if (!rewritten) {
|
||||
ret = error(_("cannot drop root commit %s: "
|
||||
"it has no parent to replay onto"),
|
||||
argv[0]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
skip_commit = true;
|
||||
break;
|
||||
case REPLAY_EMPTY_COMMIT_KEEP:
|
||||
/* Proceed and record the empty commit. */
|
||||
break;
|
||||
case REPLAY_EMPTY_COMMIT_ABORT:
|
||||
ret = error(_("fixup makes commit %s empty"), argv[0]);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = setup_revwalk(repo, action, original, &revs);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!skip_commit) {
|
||||
ret = commit_tree_ext(repo, "fixup", original, original->parents,
|
||||
&original_tree->object.oid, &merge_result.tree->object.oid,
|
||||
&rewritten, flags);
|
||||
if (ret < 0) {
|
||||
ret = error(_("failed writing fixed-up commit"));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
strbuf_addf(&reflog_msg, "fixup: updating %s", argv[0]);
|
||||
|
||||
ret = handle_reference_updates(&revs, action, original, rewritten,
|
||||
reflog_msg.buf, dry_run, empty);
|
||||
if (ret < 0) {
|
||||
ret = error(_("failed replaying descendants"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
merge_finalize(&merge_opts, &merge_result);
|
||||
strbuf_release(&reflog_msg);
|
||||
release_revisions(&revs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cmd_history_reword(int argc,
|
||||
const char **argv,
|
||||
const char *prefix,
|
||||
|
|
@ -478,7 +723,7 @@ static int cmd_history_reword(int argc,
|
|||
strbuf_addf(&reflog_msg, "reword: updating %s", argv[0]);
|
||||
|
||||
ret = handle_reference_updates(&revs, action, original, rewritten,
|
||||
reflog_msg.buf, dry_run);
|
||||
reflog_msg.buf, dry_run, REPLAY_EMPTY_COMMIT_ABORT);
|
||||
if (ret < 0) {
|
||||
ret = error(_("failed replaying descendants"));
|
||||
goto out;
|
||||
|
|
@ -616,9 +861,8 @@ static int split_commit(struct repository *repo,
|
|||
* The first commit is constructed from the split-out tree. The base
|
||||
* that shall be diffed against is the parent of the original commit.
|
||||
*/
|
||||
ret = commit_tree_with_edited_message_ext(repo, "split-out", original,
|
||||
original->parents, &parent_tree_oid,
|
||||
&split_tree->object.oid, &first_commit);
|
||||
ret = commit_tree_ext(repo, "split-out", original, original->parents, &parent_tree_oid,
|
||||
&split_tree->object.oid, &first_commit, COMMIT_TREE_EDIT_MESSAGE);
|
||||
if (ret < 0) {
|
||||
ret = error(_("failed writing first commit"));
|
||||
goto out;
|
||||
|
|
@ -634,9 +878,8 @@ static int split_commit(struct repository *repo,
|
|||
old_tree_oid = &repo_get_commit_tree(repo, first_commit)->object.oid;
|
||||
new_tree_oid = &repo_get_commit_tree(repo, original)->object.oid;
|
||||
|
||||
ret = commit_tree_with_edited_message_ext(repo, "split-out", original,
|
||||
parents, old_tree_oid,
|
||||
new_tree_oid, &second_commit);
|
||||
ret = commit_tree_ext(repo, "split-out", original, parents, old_tree_oid,
|
||||
new_tree_oid, &second_commit, COMMIT_TREE_EDIT_MESSAGE);
|
||||
if (ret < 0) {
|
||||
ret = error(_("failed writing second commit"));
|
||||
goto out;
|
||||
|
|
@ -717,7 +960,7 @@ static int cmd_history_split(int argc,
|
|||
strbuf_addf(&reflog_msg, "split: updating %s", argv[0]);
|
||||
|
||||
ret = handle_reference_updates(&revs, action, original, rewritten,
|
||||
reflog_msg.buf, dry_run);
|
||||
reflog_msg.buf, dry_run, REPLAY_EMPTY_COMMIT_ABORT);
|
||||
if (ret < 0) {
|
||||
ret = error(_("failed replaying descendants"));
|
||||
goto out;
|
||||
|
|
@ -738,12 +981,14 @@ int cmd_history(int argc,
|
|||
struct repository *repo)
|
||||
{
|
||||
const char * const usage[] = {
|
||||
GIT_HISTORY_FIXUP_USAGE,
|
||||
GIT_HISTORY_REWORD_USAGE,
|
||||
GIT_HISTORY_SPLIT_USAGE,
|
||||
NULL,
|
||||
};
|
||||
parse_opt_subcommand_fn *fn = NULL;
|
||||
struct option options[] = {
|
||||
OPT_SUBCOMMAND("fixup", &fn, cmd_history_fixup),
|
||||
OPT_SUBCOMMAND("reword", &fn, cmd_history_reword),
|
||||
OPT_SUBCOMMAND("split", &fn, cmd_history_split),
|
||||
OPT_END(),
|
||||
|
|
|
|||
|
|
@ -4,23 +4,15 @@
|
|||
#include "environment.h"
|
||||
#include "gettext.h"
|
||||
#include "hook.h"
|
||||
#include "hook-list.h"
|
||||
#include "parse-options.h"
|
||||
#include "thread-utils.h"
|
||||
|
||||
#define BUILTIN_HOOK_RUN_USAGE \
|
||||
N_("git hook run [--allow-unknown-hook-name] [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-args>]")
|
||||
N_("git hook run [--allow-unknown-hook-name] [--ignore-missing] [--to-stdin=<path>] [(-j|--jobs) <n>]\n" \
|
||||
"<hook-name> [-- <hook-args>]")
|
||||
#define BUILTIN_HOOK_LIST_USAGE \
|
||||
N_("git hook list [--allow-unknown-hook-name] [-z] [--show-scope] <hook-name>")
|
||||
|
||||
static int is_known_hook(const char *name)
|
||||
{
|
||||
const char **p;
|
||||
for (p = hook_name_list; *p; p++)
|
||||
if (!strcmp(*p, name))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * const builtin_hook_usage[] = {
|
||||
BUILTIN_HOOK_RUN_USAGE,
|
||||
BUILTIN_HOOK_LIST_USAGE,
|
||||
|
|
@ -96,14 +88,22 @@ static int list(int argc, const char **argv, const char *prefix,
|
|||
const char *name = h->u.configured.friendly_name;
|
||||
const char *scope = show_scope ?
|
||||
config_scope_name(h->u.configured.scope) : NULL;
|
||||
/*
|
||||
* Show the most relevant disable reason. Event-level
|
||||
* takes precedence: if the whole event is off, that
|
||||
* is what the user needs to know. The per-hook
|
||||
* "disabled" surfaces once the event is re-enabled.
|
||||
*/
|
||||
const char *disability =
|
||||
h->u.configured.event_disabled ? "event-disabled\t" :
|
||||
h->u.configured.disabled ? "disabled\t" :
|
||||
"";
|
||||
if (scope)
|
||||
printf("%s\t%s%s%c", scope,
|
||||
h->u.configured.disabled ? "disabled\t" : "",
|
||||
name, line_terminator);
|
||||
printf("%s\t%s%s%c", scope, disability, name,
|
||||
line_terminator);
|
||||
else
|
||||
printf("%s%s%c",
|
||||
h->u.configured.disabled ? "disabled\t" : "",
|
||||
name, line_terminator);
|
||||
printf("%s%s%c", disability, name,
|
||||
line_terminator);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -124,6 +124,7 @@ static int run(int argc, const char **argv, const char *prefix,
|
|||
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
|
||||
int ignore_missing = 0;
|
||||
int allow_unknown = 0;
|
||||
int jobs = 0;
|
||||
const char *hook_name;
|
||||
struct option run_options[] = {
|
||||
OPT_BOOL(0, "allow-unknown-hook-name", &allow_unknown,
|
||||
|
|
@ -132,6 +133,8 @@ static int run(int argc, const char **argv, const char *prefix,
|
|||
N_("silently ignore missing requested <hook-name>")),
|
||||
OPT_STRING(0, "to-stdin", &opt.path_to_stdin, N_("path"),
|
||||
N_("file to read into hooks' stdin")),
|
||||
OPT_INTEGER('j', "jobs", &jobs,
|
||||
N_("run up to <n> hooks simultaneously (-1 for CPU count)")),
|
||||
OPT_END(),
|
||||
};
|
||||
int ret;
|
||||
|
|
@ -140,6 +143,15 @@ static int run(int argc, const char **argv, const char *prefix,
|
|||
builtin_hook_run_usage,
|
||||
PARSE_OPT_KEEP_DASHDASH);
|
||||
|
||||
if (jobs == -1)
|
||||
opt.jobs = online_cpus();
|
||||
else if (jobs < 0)
|
||||
die(_("invalid value for -j: %d"
|
||||
" (use -1 for CPU count or a"
|
||||
" positive integer)"), jobs);
|
||||
else
|
||||
opt.jobs = jobs;
|
||||
|
||||
if (!argc)
|
||||
goto usage;
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ static const char index_pack_usage[] =
|
|||
|
||||
struct object_entry {
|
||||
struct pack_idx_entry idx;
|
||||
unsigned long size;
|
||||
size_t size;
|
||||
unsigned char hdr_size;
|
||||
signed char type;
|
||||
signed char real_type;
|
||||
|
|
@ -145,8 +145,7 @@ static int check_self_contained_and_connected;
|
|||
|
||||
static struct progress *progress;
|
||||
|
||||
/* We always read in 4kB chunks. */
|
||||
static unsigned char input_buffer[4096];
|
||||
static unsigned char input_buffer[DEFAULT_IO_BUFFER_SIZE];
|
||||
static unsigned int input_offset, input_len;
|
||||
static off_t consumed_bytes;
|
||||
static off_t max_input_size;
|
||||
|
|
@ -469,7 +468,7 @@ static int is_delta_type(enum object_type type)
|
|||
return (type == OBJ_REF_DELTA || type == OBJ_OFS_DELTA);
|
||||
}
|
||||
|
||||
static void *unpack_entry_data(off_t offset, unsigned long size,
|
||||
static void *unpack_entry_data(off_t offset, size_t size,
|
||||
enum object_type type, struct object_id *oid)
|
||||
{
|
||||
static char fixed_buf[8192];
|
||||
|
|
@ -524,7 +523,7 @@ static void *unpack_raw_entry(struct object_entry *obj,
|
|||
struct object_id *oid)
|
||||
{
|
||||
unsigned char *p;
|
||||
unsigned long size, c;
|
||||
size_t size, c;
|
||||
off_t base_offset;
|
||||
unsigned shift;
|
||||
void *data;
|
||||
|
|
@ -539,6 +538,8 @@ static void *unpack_raw_entry(struct object_entry *obj,
|
|||
size = (c & 15);
|
||||
shift = 4;
|
||||
while (c & 0x80) {
|
||||
if ((bitsizeof(size_t) - 7) < shift)
|
||||
die(_("object size too large for this platform"));
|
||||
p = fill(1);
|
||||
c = *p;
|
||||
use(1);
|
||||
|
|
|
|||
|
|
@ -237,9 +237,9 @@ int cmd_init_db(int argc,
|
|||
if (!git_work_tree_cfg)
|
||||
git_work_tree_cfg = xgetcwd();
|
||||
if (work_tree)
|
||||
set_git_work_tree(work_tree);
|
||||
set_git_work_tree(the_repository, work_tree);
|
||||
else
|
||||
set_git_work_tree(git_work_tree_cfg);
|
||||
set_git_work_tree(the_repository, git_work_tree_cfg);
|
||||
if (access(repo_get_work_tree(the_repository), X_OK))
|
||||
die_errno (_("Cannot access work tree '%s'"),
|
||||
repo_get_work_tree(the_repository));
|
||||
|
|
@ -248,11 +248,11 @@ int cmd_init_db(int argc,
|
|||
if (real_git_dir)
|
||||
die(_("--separate-git-dir incompatible with bare repository"));
|
||||
if (work_tree)
|
||||
set_git_work_tree(work_tree);
|
||||
set_git_work_tree(the_repository, work_tree);
|
||||
}
|
||||
|
||||
flags |= INIT_DB_EXIST_OK;
|
||||
ret = init_db(git_dir, real_git_dir, template_dir, hash_algo,
|
||||
ret = init_db(the_repository, git_dir, real_git_dir, template_dir, hash_algo,
|
||||
ref_storage_format, initial_branch,
|
||||
init_shared_repository, flags);
|
||||
|
||||
|
|
|
|||
131
builtin/log.c
131
builtin/log.c
|
|
@ -21,10 +21,12 @@
|
|||
#include "color.h"
|
||||
#include "commit.h"
|
||||
#include "diff.h"
|
||||
#include "diffcore.h"
|
||||
#include "diff-merges.h"
|
||||
#include "revision.h"
|
||||
#include "log-tree.h"
|
||||
#include "oid-array.h"
|
||||
#include "oidset.h"
|
||||
#include "tag.h"
|
||||
#include "reflog-walk.h"
|
||||
#include "patch-ids.h"
|
||||
|
|
@ -43,9 +45,11 @@
|
|||
#include "utf8.h"
|
||||
|
||||
#include "commit-reach.h"
|
||||
#include "promisor-remote.h"
|
||||
#include "range-diff.h"
|
||||
#include "tmp-objdir.h"
|
||||
#include "tree.h"
|
||||
#include "userdiff.h"
|
||||
#include "write-or-die.h"
|
||||
|
||||
#define MAIL_DEFAULT_WRAP 72
|
||||
|
|
@ -2602,6 +2606,131 @@ static void print_commit(char sign, struct commit *commit, int verbose,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Enumerate blob OIDs from a single commit's diff, inserting them into blobs.
|
||||
* Skips files whose userdiff driver explicitly declares binary status
|
||||
* (drv->binary > 0), since patch-ID uses oid_to_hex() for those and
|
||||
* never reads blob content. Use userdiff_find_by_path() since
|
||||
* diff_filespec_load_driver() is static in diff.c.
|
||||
*
|
||||
* Clean up with diff_queue_clear() (from diffcore.h).
|
||||
*/
|
||||
static void collect_diff_blob_oids(struct commit *commit,
|
||||
struct diff_options *opts,
|
||||
struct oidset *blobs)
|
||||
{
|
||||
struct diff_queue_struct *q;
|
||||
|
||||
/*
|
||||
* Merge commits are filtered out by patch_id_defined() in patch-ids.c,
|
||||
* so we'll never be called with one.
|
||||
*/
|
||||
assert(!commit->parents || !commit->parents->next);
|
||||
|
||||
if (commit->parents)
|
||||
diff_tree_oid(&commit->parents->item->object.oid,
|
||||
&commit->object.oid, "", opts);
|
||||
else
|
||||
diff_root_tree_oid(&commit->object.oid, "", opts);
|
||||
diffcore_std(opts);
|
||||
|
||||
q = &diff_queued_diff;
|
||||
for (int i = 0; i < q->nr; i++) {
|
||||
struct diff_filepair *p = q->queue[i];
|
||||
struct userdiff_driver *drv;
|
||||
|
||||
/* Skip binary files */
|
||||
drv = userdiff_find_by_path(opts->repo->index, p->one->path);
|
||||
if (drv && drv->binary > 0)
|
||||
continue;
|
||||
|
||||
if (DIFF_FILE_VALID(p->one) &&
|
||||
odb_read_object_info_extended(opts->repo->objects,
|
||||
&p->one->oid, NULL,
|
||||
OBJECT_INFO_FOR_PREFETCH))
|
||||
oidset_insert(blobs, &p->one->oid);
|
||||
if (DIFF_FILE_VALID(p->two) &&
|
||||
odb_read_object_info_extended(opts->repo->objects,
|
||||
&p->two->oid, NULL,
|
||||
OBJECT_INFO_FOR_PREFETCH))
|
||||
oidset_insert(blobs, &p->two->oid);
|
||||
}
|
||||
diff_queue_clear(q);
|
||||
}
|
||||
|
||||
static int always_match(const void *cmp_data UNUSED,
|
||||
const struct hashmap_entry *entry1 UNUSED,
|
||||
const struct hashmap_entry *entry2 UNUSED,
|
||||
const void *keydata UNUSED)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prefetch blobs for git cherry in partial clones.
|
||||
*
|
||||
* Called between the revision walk (which builds the head-side
|
||||
* commit list) and the has_commit_patch_id() comparison loop.
|
||||
*
|
||||
* Uses a cmpfn-swap trick to avoid reading blobs: temporarily
|
||||
* replaces the hashmap's comparison function with a trivial
|
||||
* always-match function, so hashmap_get()/hashmap_get_next() match
|
||||
* any entry with the same oidhash bucket. These are the set of oids
|
||||
* that would trigger patch_id_neq() during normal lookup and cause
|
||||
* blobs to be read on demand, and we want to prefetch them all at
|
||||
* once instead.
|
||||
*/
|
||||
static void prefetch_cherry_blobs(struct repository *repo,
|
||||
struct commit_list *list,
|
||||
struct patch_ids *ids)
|
||||
{
|
||||
struct oidset blobs = OIDSET_INIT;
|
||||
hashmap_cmp_fn original_cmpfn;
|
||||
|
||||
/* Exit if we're not in a partial clone */
|
||||
if (!repo_has_promisor_remote(repo))
|
||||
return;
|
||||
|
||||
/* Save original cmpfn, replace with always_match */
|
||||
original_cmpfn = ids->patches.cmpfn;
|
||||
ids->patches.cmpfn = always_match;
|
||||
|
||||
/* Find header-only collisions, gather blobs from those commits */
|
||||
for (struct commit_list *l = list; l; l = l->next) {
|
||||
struct commit *c = l->item;
|
||||
bool match_found = false;
|
||||
for (struct patch_id *cur = patch_id_iter_first(c, ids);
|
||||
cur;
|
||||
cur = patch_id_iter_next(cur, ids)) {
|
||||
match_found = true;
|
||||
collect_diff_blob_oids(cur->commit, &ids->diffopts,
|
||||
&blobs);
|
||||
}
|
||||
if (match_found)
|
||||
collect_diff_blob_oids(c, &ids->diffopts, &blobs);
|
||||
}
|
||||
|
||||
/* Restore original cmpfn */
|
||||
ids->patches.cmpfn = original_cmpfn;
|
||||
|
||||
/* If we have any blobs to fetch, fetch them */
|
||||
if (oidset_size(&blobs)) {
|
||||
struct oid_array to_fetch = OID_ARRAY_INIT;
|
||||
struct oidset_iter iter;
|
||||
const struct object_id *oid;
|
||||
|
||||
oidset_iter_init(&blobs, &iter);
|
||||
while ((oid = oidset_iter_next(&iter)))
|
||||
oid_array_append(&to_fetch, oid);
|
||||
|
||||
promisor_remote_get_direct(repo, to_fetch.oid, to_fetch.nr);
|
||||
|
||||
oid_array_clear(&to_fetch);
|
||||
}
|
||||
|
||||
oidset_clear(&blobs);
|
||||
}
|
||||
|
||||
int cmd_cherry(int argc,
|
||||
const char **argv,
|
||||
const char *prefix,
|
||||
|
|
@ -2673,6 +2802,8 @@ int cmd_cherry(int argc,
|
|||
commit_list_insert(commit, &list);
|
||||
}
|
||||
|
||||
prefetch_cherry_blobs(the_repository, list, &ids);
|
||||
|
||||
for (struct commit_list *l = list; l; l = l->next) {
|
||||
char sign = '+';
|
||||
|
||||
|
|
|
|||
|
|
@ -703,8 +703,8 @@ int cmd_ls_files(int argc,
|
|||
if (dir.exclude_per_dir)
|
||||
exc_given = 1;
|
||||
|
||||
if (require_work_tree && !is_inside_work_tree())
|
||||
setup_work_tree();
|
||||
if (require_work_tree && !is_inside_work_tree(repo))
|
||||
setup_work_tree(repo);
|
||||
|
||||
if (recurse_submodules &&
|
||||
(show_deleted || show_others || show_unmerged ||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,12 @@
|
|||
|
||||
static int show_merge_base(struct commit **rev, size_t rev_nr, int show_all)
|
||||
{
|
||||
enum merge_base_flags flags = show_all ? MERGE_BASE_FIND_ALL : 0;
|
||||
struct commit_list *result = NULL, *r;
|
||||
|
||||
if (repo_get_merge_bases_many_dirty(the_repository, rev[0],
|
||||
rev_nr - 1, rev + 1, &result) < 0) {
|
||||
rev_nr - 1, rev + 1,
|
||||
flags, &result) < 0) {
|
||||
commit_list_free(result);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ int cmd_merge_file(int argc,
|
|||
|
||||
if (!repo && object_id)
|
||||
/* emit the correct "not a git repo" error in this case */
|
||||
setup_git_directory();
|
||||
setup_git_directory(the_repository);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
char *fname;
|
||||
|
|
|
|||
|
|
@ -537,7 +537,8 @@ static void finish(struct commit *head_commit,
|
|||
run_hooks_l(the_repository, "post-merge", squash ? "1" : "0", NULL);
|
||||
|
||||
if (new_head)
|
||||
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
|
||||
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH",
|
||||
NULL, NULL, NULL, NULL);
|
||||
strbuf_release(&reflog_message);
|
||||
}
|
||||
|
||||
|
|
@ -1672,12 +1673,14 @@ int cmd_merge(int argc,
|
|||
}
|
||||
|
||||
if (autostash)
|
||||
create_autostash_ref(the_repository, "MERGE_AUTOSTASH");
|
||||
create_autostash_ref(the_repository, "MERGE_AUTOSTASH",
|
||||
NULL, false);
|
||||
if (checkout_fast_forward(the_repository,
|
||||
&head_commit->object.oid,
|
||||
&commit->object.oid,
|
||||
overwrite_ignore)) {
|
||||
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
|
||||
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH",
|
||||
NULL, NULL, NULL, NULL);
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -1735,21 +1738,11 @@ int cmd_merge(int argc,
|
|||
struct commit_list *j;
|
||||
|
||||
for (j = remoteheads; j; j = j->next) {
|
||||
struct commit_list *common_one = NULL;
|
||||
struct commit *common_item;
|
||||
|
||||
/*
|
||||
* Here we *have* to calculate the individual
|
||||
* merge_bases again, otherwise "git merge HEAD^
|
||||
* HEAD^^" would be missed.
|
||||
*/
|
||||
if (repo_get_merge_bases(the_repository, head_commit,
|
||||
j->item, &common_one) < 0)
|
||||
int ret = repo_in_merge_bases(the_repository,
|
||||
j->item, head_commit);
|
||||
if (ret < 0)
|
||||
exit(128);
|
||||
|
||||
common_item = common_one->item;
|
||||
commit_list_free(common_one);
|
||||
if (!oideq(&common_item->object.oid, &j->item->object.oid)) {
|
||||
if (!ret) {
|
||||
up_to_date = 0;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1764,7 +1757,8 @@ int cmd_merge(int argc,
|
|||
die_ff_impossible();
|
||||
|
||||
if (autostash)
|
||||
create_autostash_ref(the_repository, "MERGE_AUTOSTASH");
|
||||
create_autostash_ref(the_repository, "MERGE_AUTOSTASH",
|
||||
NULL, false);
|
||||
|
||||
/* We are going to make a new commit. */
|
||||
git_committer_info(IDENT_STRICT);
|
||||
|
|
@ -1849,7 +1843,8 @@ int cmd_merge(int argc,
|
|||
else
|
||||
fprintf(stderr, _("Merge with strategy %s failed.\n"),
|
||||
use_strategies[0]->name);
|
||||
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
|
||||
apply_autostash_ref(the_repository, "MERGE_AUTOSTASH",
|
||||
NULL, NULL, NULL, NULL);
|
||||
ret = 2;
|
||||
goto done;
|
||||
} else if (best_strategy == wt_strategy)
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@
|
|||
#define BUILTIN_MIDX_WRITE_USAGE \
|
||||
N_("git multi-pack-index [<options>] write [--preferred-pack=<pack>]\n" \
|
||||
" [--[no-]bitmap] [--[no-]incremental] [--[no-]stdin-packs]\n" \
|
||||
" [--refs-snapshot=<path>]")
|
||||
" [--refs-snapshot=<path>] [--[no-]write-chain-file]\n" \
|
||||
" [--base=<checksum>]")
|
||||
|
||||
#define BUILTIN_MIDX_COMPACT_USAGE \
|
||||
N_("git multi-pack-index [<options>] compact [--[no-]incremental]\n" \
|
||||
" [--[no-]bitmap] <from> <to>")
|
||||
" [--[no-]bitmap] [--base=<checksum>] [--[no-]write-chain-file]\n" \
|
||||
" <from> <to>")
|
||||
|
||||
#define BUILTIN_MIDX_VERIFY_USAGE \
|
||||
N_("git multi-pack-index [<options>] verify")
|
||||
|
|
@ -63,6 +65,7 @@ static char const * const builtin_multi_pack_index_usage[] = {
|
|||
static struct opts_multi_pack_index {
|
||||
char *object_dir;
|
||||
const char *preferred_pack;
|
||||
const char *incremental_base;
|
||||
char *refs_snapshot;
|
||||
unsigned long batch_size;
|
||||
unsigned flags;
|
||||
|
|
@ -151,8 +154,13 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
|
|||
N_("pack for reuse when computing a multi-pack bitmap")),
|
||||
OPT_BIT(0, "bitmap", &opts.flags, N_("write multi-pack bitmap"),
|
||||
MIDX_WRITE_BITMAP | MIDX_WRITE_REV_INDEX),
|
||||
OPT_STRING(0, "base", &opts.incremental_base, N_("checksum"),
|
||||
N_("base MIDX for incremental writes")),
|
||||
OPT_BIT(0, "incremental", &opts.flags,
|
||||
N_("write a new incremental MIDX"), MIDX_WRITE_INCREMENTAL),
|
||||
OPT_NEGBIT(0, "write-chain-file", &opts.flags,
|
||||
N_("write the multi-pack-index chain file"),
|
||||
MIDX_WRITE_NO_CHAIN),
|
||||
OPT_BOOL(0, "stdin-packs", &opts.stdin_packs,
|
||||
N_("write multi-pack index containing only given indexes")),
|
||||
OPT_FILENAME(0, "refs-snapshot", &opts.refs_snapshot,
|
||||
|
|
@ -178,6 +186,22 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
|
|||
if (argc)
|
||||
usage_with_options(builtin_multi_pack_index_write_usage,
|
||||
options);
|
||||
|
||||
if (opts.flags & MIDX_WRITE_NO_CHAIN &&
|
||||
!(opts.flags & MIDX_WRITE_INCREMENTAL)) {
|
||||
error(_("cannot use %s without %s"),
|
||||
"--no-write-chain-file", "--incremental");
|
||||
usage_with_options(builtin_multi_pack_index_write_usage,
|
||||
options);
|
||||
}
|
||||
|
||||
if (opts.incremental_base &&
|
||||
!(opts.flags & MIDX_WRITE_NO_CHAIN)) {
|
||||
error(_("cannot use --base without --no-write-chain-file"));
|
||||
usage_with_options(builtin_multi_pack_index_write_usage,
|
||||
options);
|
||||
}
|
||||
|
||||
source = handle_object_dir_option(repo);
|
||||
|
||||
FREE_AND_NULL(options);
|
||||
|
|
@ -189,7 +213,8 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
|
|||
|
||||
ret = write_midx_file_only(source, &packs,
|
||||
opts.preferred_pack,
|
||||
opts.refs_snapshot, opts.flags);
|
||||
opts.refs_snapshot,
|
||||
opts.incremental_base, opts.flags);
|
||||
|
||||
string_list_clear(&packs, 0);
|
||||
free(opts.refs_snapshot);
|
||||
|
|
@ -217,10 +242,15 @@ static int cmd_multi_pack_index_compact(int argc, const char **argv,
|
|||
|
||||
struct option *options;
|
||||
static struct option builtin_multi_pack_index_compact_options[] = {
|
||||
OPT_STRING(0, "base", &opts.incremental_base, N_("checksum"),
|
||||
N_("base MIDX for incremental writes")),
|
||||
OPT_BIT(0, "bitmap", &opts.flags, N_("write multi-pack bitmap"),
|
||||
MIDX_WRITE_BITMAP | MIDX_WRITE_REV_INDEX),
|
||||
OPT_BIT(0, "incremental", &opts.flags,
|
||||
N_("write a new incremental MIDX"), MIDX_WRITE_INCREMENTAL),
|
||||
OPT_NEGBIT(0, "write-chain-file", &opts.flags,
|
||||
N_("write the multi-pack-index chain file"),
|
||||
MIDX_WRITE_NO_CHAIN),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
|
|
@ -239,6 +269,15 @@ static int cmd_multi_pack_index_compact(int argc, const char **argv,
|
|||
if (argc != 2)
|
||||
usage_with_options(builtin_multi_pack_index_compact_usage,
|
||||
options);
|
||||
|
||||
if (opts.flags & MIDX_WRITE_NO_CHAIN &&
|
||||
!(opts.flags & MIDX_WRITE_INCREMENTAL)) {
|
||||
error(_("cannot use %s without %s"),
|
||||
"--no-write-chain-file", "--incremental");
|
||||
usage_with_options(builtin_multi_pack_index_compact_usage,
|
||||
options);
|
||||
}
|
||||
|
||||
source = handle_object_dir_option(the_repository);
|
||||
|
||||
FREE_AND_NULL(options);
|
||||
|
|
@ -266,7 +305,8 @@ static int cmd_multi_pack_index_compact(int argc, const char **argv,
|
|||
die(_("MIDX %s must be an ancestor of %s"), argv[0], argv[1]);
|
||||
}
|
||||
|
||||
ret = write_midx_file_compact(source, from_midx, to_midx, opts.flags);
|
||||
ret = write_midx_file_compact(source, from_midx, to_midx,
|
||||
opts.incremental_base, opts.flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ static void internal_prefix_pathspec(struct strvec *out,
|
|||
|
||||
trimmed = xmemdupz(pathspec[i], to_copy);
|
||||
maybe_basename = (flags & DUP_BASENAME) ? basename(trimmed) : trimmed;
|
||||
prefixed_path = prefix_path(prefix, prefixlen, maybe_basename);
|
||||
prefixed_path = prefix_path(the_repository, prefix, prefixlen, maybe_basename);
|
||||
strvec_push(out, prefixed_path);
|
||||
|
||||
free(prefixed_path);
|
||||
|
|
@ -394,7 +394,8 @@ dir_check:
|
|||
for (j = 0; j < last - first; j++) {
|
||||
const struct cache_entry *ce = the_repository->index->cache[first + j];
|
||||
const char *path = ce->name;
|
||||
char *prefixed_path = prefix_path(dst_with_slash, dst_with_slash_len, path + length + 1);
|
||||
char *prefixed_path = prefix_path(the_repository, dst_with_slash,
|
||||
dst_with_slash_len, path + length + 1);
|
||||
|
||||
strvec_push(&sources, path);
|
||||
strvec_push(&destinations, prefixed_path);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@
|
|||
#include "commit-graph.h"
|
||||
#include "wildmatch.h"
|
||||
#include "mem-pool.h"
|
||||
#include "pretty.h"
|
||||
#include "revision.h"
|
||||
#include "notes.h"
|
||||
#include "write-or-die.h"
|
||||
|
||||
/*
|
||||
* One day. See the 'name a rev shortly after epoch' test in t6120 when
|
||||
|
|
@ -270,6 +274,43 @@ struct name_ref_data {
|
|||
struct string_list exclude_filters;
|
||||
};
|
||||
|
||||
struct pretty_format {
|
||||
struct pretty_print_context ctx;
|
||||
struct userformat_want want;
|
||||
};
|
||||
|
||||
enum command_type {
|
||||
NAME_REV = 1,
|
||||
FORMAT_REV = 2,
|
||||
};
|
||||
|
||||
enum stdin_mode {
|
||||
TEXT = 1,
|
||||
REVS = 2,
|
||||
};
|
||||
|
||||
struct command {
|
||||
enum command_type type;
|
||||
union {
|
||||
int name_only;
|
||||
struct pretty_format *pretty_format;
|
||||
} u;
|
||||
};
|
||||
|
||||
static void init_name_rev_command(struct command *cmd,
|
||||
int name_only)
|
||||
{
|
||||
cmd->type = NAME_REV;
|
||||
cmd->u.name_only = name_only;
|
||||
}
|
||||
|
||||
static void init_format_rev_command(struct command *cmd,
|
||||
struct pretty_format *pretty_format)
|
||||
{
|
||||
cmd->type = FORMAT_REV;
|
||||
cmd->u.pretty_format = pretty_format;
|
||||
}
|
||||
|
||||
static struct tip_table {
|
||||
struct tip_table_entry {
|
||||
struct object_id oid;
|
||||
|
|
@ -464,9 +505,9 @@ static const char *get_rev_name(const struct object *o, struct strbuf *buf)
|
|||
if (!n)
|
||||
return NULL;
|
||||
|
||||
if (!n->generation)
|
||||
if (!n->generation) {
|
||||
return n->tip_name;
|
||||
else {
|
||||
} else {
|
||||
strbuf_reset(buf);
|
||||
strbuf_addstr(buf, n->tip_name);
|
||||
strbuf_strip_suffix(buf, "^0");
|
||||
|
|
@ -475,6 +516,27 @@ static const char *get_rev_name(const struct object *o, struct strbuf *buf)
|
|||
}
|
||||
}
|
||||
|
||||
static const char *get_format_rev(const struct commit *c,
|
||||
struct pretty_format *format_ctx,
|
||||
struct strbuf *buf)
|
||||
{
|
||||
strbuf_reset(buf);
|
||||
|
||||
if (format_ctx->want.notes) {
|
||||
struct strbuf notebuf = STRBUF_INIT;
|
||||
|
||||
format_display_notes(&c->object.oid, ¬ebuf,
|
||||
get_log_output_encoding(),
|
||||
format_ctx->ctx.fmt == CMIT_FMT_USERFORMAT);
|
||||
format_ctx->ctx.notes_message = strbuf_detach(¬ebuf, NULL);
|
||||
}
|
||||
|
||||
pretty_print_commit(&format_ctx->ctx, c, buf);
|
||||
FREE_AND_NULL(format_ctx->ctx.notes_message);
|
||||
|
||||
return buf->buf;
|
||||
}
|
||||
|
||||
static void show_name(const struct object *obj,
|
||||
const char *caller_name,
|
||||
int always, int allow_undefined, int name_only)
|
||||
|
|
@ -505,7 +567,7 @@ static char const * const name_rev_usage[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static void name_rev_line(char *p, struct name_ref_data *data)
|
||||
static void name_rev_line(char *p, struct command *cmd)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
int counter = 0;
|
||||
|
|
@ -514,33 +576,52 @@ static void name_rev_line(char *p, struct name_ref_data *data)
|
|||
|
||||
for (p_start = p; *p; p++) {
|
||||
#define ishex(x) (isdigit((x)) || ((x) >= 'a' && (x) <= 'f'))
|
||||
if (!ishex(*p))
|
||||
if (!ishex(*p)) {
|
||||
counter = 0;
|
||||
else if (++counter == hexsz &&
|
||||
!ishex(*(p+1))) {
|
||||
} else if (++counter == hexsz &&
|
||||
!ishex(*(p + 1))) {
|
||||
struct object_id oid;
|
||||
const char *name = NULL;
|
||||
char c = *(p+1);
|
||||
char c = *(p + 1);
|
||||
int p_len = p - p_start + 1;
|
||||
struct object *o = NULL;
|
||||
int oid_ret = 1;
|
||||
|
||||
counter = 0;
|
||||
|
||||
*(p+1) = 0;
|
||||
if (!repo_get_oid(the_repository, p - (hexsz - 1), &oid)) {
|
||||
struct object *o =
|
||||
lookup_object(the_repository, &oid);
|
||||
*(p + 1) = 0;
|
||||
oid_ret = repo_get_oid(the_repository, p - (hexsz - 1), &oid);
|
||||
*(p + 1) = c;
|
||||
|
||||
switch (cmd->type) {
|
||||
case NAME_REV:
|
||||
if (!oid_ret)
|
||||
o = lookup_object(the_repository, &oid);
|
||||
if (o)
|
||||
name = get_rev_name(o, &buf);
|
||||
if (!name)
|
||||
continue;
|
||||
if (cmd->u.name_only)
|
||||
printf("%.*s%s", p_len - hexsz, p_start, name);
|
||||
else
|
||||
printf("%.*s (%s)", p_len, p_start, name);
|
||||
break;
|
||||
case FORMAT_REV:
|
||||
if (!oid_ret)
|
||||
o = parse_object(the_repository, &oid);
|
||||
if (o && o->type == OBJ_COMMIT)
|
||||
name = get_format_rev((const struct commit *)o,
|
||||
cmd->u.pretty_format,
|
||||
&buf);
|
||||
if (name)
|
||||
printf("%.*s%s", p_len - hexsz, p_start, name);
|
||||
else
|
||||
printf("%.*s", p_len, p_start);
|
||||
break;
|
||||
default:
|
||||
BUG("uncovered case: %d", cmd->type);
|
||||
}
|
||||
*(p+1) = c;
|
||||
|
||||
if (!name)
|
||||
continue;
|
||||
|
||||
if (data->name_only)
|
||||
printf("%.*s%s", p_len - hexsz, p_start, name);
|
||||
else
|
||||
printf("%.*s (%s)", p_len, p_start, name);
|
||||
p_start = p + 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -565,13 +646,14 @@ int cmd_name_rev(int argc,
|
|||
#endif
|
||||
int all = 0, annotate_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
|
||||
struct name_ref_data data = { 0, 0, STRING_LIST_INIT_NODUP, STRING_LIST_INIT_NODUP };
|
||||
struct command cmd;
|
||||
struct option opts[] = {
|
||||
OPT_BOOL(0, "name-only", &data.name_only, N_("print only ref-based names (no object names)")),
|
||||
OPT_BOOL(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
|
||||
OPT_STRING_LIST(0, "refs", &data.ref_filters, N_("pattern"),
|
||||
N_("only use refs matching <pattern>")),
|
||||
N_("only use refs matching <pattern>")),
|
||||
OPT_STRING_LIST(0, "exclude", &data.exclude_filters, N_("pattern"),
|
||||
N_("ignore refs matching <pattern>")),
|
||||
N_("ignore refs matching <pattern>")),
|
||||
OPT_GROUP(""),
|
||||
OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")),
|
||||
#ifndef WITH_BREAKING_CHANGES
|
||||
|
|
@ -583,10 +665,10 @@ int cmd_name_rev(int argc,
|
|||
#endif /* WITH_BREAKING_CHANGES */
|
||||
OPT_BOOL(0, "annotate-stdin", &annotate_stdin, N_("annotate text from stdin")),
|
||||
OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")),
|
||||
OPT_BOOL(0, "always", &always,
|
||||
N_("show abbreviated commit object as fallback")),
|
||||
OPT_BOOL(0, "always", &always,
|
||||
N_("show abbreviated commit object as fallback")),
|
||||
OPT_HIDDEN_BOOL(0, "peel-tag", &peel_tag,
|
||||
N_("dereference tags in the input (internal use)")),
|
||||
N_("dereference tags in the input (internal use)")),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
|
|
@ -594,6 +676,7 @@ int cmd_name_rev(int argc,
|
|||
init_commit_rev_name(&rev_names);
|
||||
repo_config(the_repository, git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
|
||||
init_name_rev_command(&cmd, data.name_only);
|
||||
|
||||
#ifndef WITH_BREAKING_CHANGES
|
||||
if (transform_stdin) {
|
||||
|
|
@ -661,7 +744,7 @@ int cmd_name_rev(int argc,
|
|||
|
||||
while (strbuf_getline(&sb, stdin) != EOF) {
|
||||
strbuf_addch(&sb, '\n');
|
||||
name_rev_line(sb.buf, &data);
|
||||
name_rev_line(sb.buf, &cmd);
|
||||
}
|
||||
strbuf_release(&sb);
|
||||
} else if (all) {
|
||||
|
|
@ -688,3 +771,170 @@ int cmd_name_rev(int argc,
|
|||
object_array_clear(&revs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct format_nul_data {
|
||||
bool nul_input;
|
||||
bool nul_output;
|
||||
};
|
||||
|
||||
static int format_nul_cb(const struct option *option,
|
||||
const char *arg,
|
||||
int unset)
|
||||
{
|
||||
struct format_nul_data *data = option->value;
|
||||
data->nul_input = 1;
|
||||
data->nul_output = 1;
|
||||
BUG_ON_OPT_NEG(unset);
|
||||
BUG_ON_OPT_ARG(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum stdin_mode parse_stdin_mode(const char *stdin_mode)
|
||||
{
|
||||
if (!strcmp(stdin_mode, "text"))
|
||||
return TEXT;
|
||||
else if (!strcmp(stdin_mode, "revs") ||
|
||||
!strcmp(stdin_mode, "rev"))
|
||||
return REVS;
|
||||
else
|
||||
die(_("'%s' needs to be either text, revs, or rev"),
|
||||
"--stdin-mode");
|
||||
}
|
||||
|
||||
static char const *const format_rev_usage[] = {
|
||||
N_("(EXPERIMENTAL!) git format-rev --stdin-mode=<mode> "
|
||||
"--format=<pretty> [--[no-]notes=<ref>] "
|
||||
"[-z] [--[no-]null-output] [--[no-]null-input]"),
|
||||
NULL
|
||||
};
|
||||
|
||||
int cmd_format_rev(int argc,
|
||||
const char **argv,
|
||||
const char *prefix,
|
||||
struct repository *repo UNUSED)
|
||||
{
|
||||
const char *format = NULL;
|
||||
enum stdin_mode stdin_mode;
|
||||
const char *stdin_mode_arg = NULL;
|
||||
struct format_nul_data nul_data = { 0, 0 };
|
||||
char output_terminator;
|
||||
strbuf_getline_fn getline_fn;
|
||||
struct display_notes_opt format_notes_opt;
|
||||
struct rev_info format_rev = REV_INFO_INIT;
|
||||
struct pretty_format format_pp = { 0 };
|
||||
struct string_list notes = STRING_LIST_INIT_NODUP;
|
||||
struct strbuf scratch_buf = STRBUF_INIT;
|
||||
struct command cmd;
|
||||
struct option opts[] = {
|
||||
OPT_STRING(0, "format", &format, N_("format"),
|
||||
N_("pretty format to use")),
|
||||
OPT_STRING(0, "stdin-mode", &stdin_mode_arg, N_("stdin-mode"),
|
||||
N_("how revs are processed")),
|
||||
OPT_STRING_LIST(0, "notes", ¬es, N_("notes"),
|
||||
N_("display notes for pretty format")),
|
||||
OPT_CALLBACK_F('z', "null", &nul_data, N_("z"),
|
||||
N_("Use NUL for input and output termination"),
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG, format_nul_cb),
|
||||
OPT_BOOL(0, "null-input", &nul_data.nul_input,
|
||||
N_("Use NUL for input termination")),
|
||||
OPT_BOOL(0, "null-output", &nul_data.nul_output,
|
||||
N_("Use NUL for output termination")),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, prefix, opts, format_rev_usage, 0);
|
||||
|
||||
if (argc > 0) {
|
||||
error(_("too many arguments"));
|
||||
usage_with_options(format_rev_usage, opts);
|
||||
}
|
||||
|
||||
if (!format)
|
||||
die(_("'%s' is required"), "--format");
|
||||
if (!stdin_mode_arg)
|
||||
die(_("'%s' is required"), "--stdin-mode");
|
||||
|
||||
getline_fn = nul_data.nul_input ? strbuf_getline_nul : strbuf_getline_lf;
|
||||
output_terminator = nul_data.nul_output ? '\0' : '\n';
|
||||
|
||||
init_display_notes(&format_notes_opt);
|
||||
stdin_mode = parse_stdin_mode(stdin_mode_arg);
|
||||
|
||||
get_commit_format(format, &format_rev);
|
||||
format_pp.ctx.rev = &format_rev;
|
||||
format_pp.ctx.fmt = format_rev.commit_format;
|
||||
format_pp.ctx.abbrev = format_rev.abbrev;
|
||||
format_pp.ctx.date_mode_explicit = format_rev.date_mode_explicit;
|
||||
format_pp.ctx.date_mode = format_rev.date_mode;
|
||||
format_pp.ctx.color = GIT_COLOR_AUTO;
|
||||
|
||||
userformat_find_requirements(format,
|
||||
&format_pp.want);
|
||||
if (format_pp.want.notes) {
|
||||
int ignore_show_notes = 0;
|
||||
struct string_list_item *n;
|
||||
|
||||
for_each_string_list_item(n, ¬es)
|
||||
enable_ref_display_notes(&format_notes_opt,
|
||||
&ignore_show_notes,
|
||||
n->string);
|
||||
load_display_notes(&format_notes_opt);
|
||||
}
|
||||
|
||||
init_format_rev_command(&cmd, &format_pp);
|
||||
|
||||
switch (stdin_mode) {
|
||||
case TEXT:
|
||||
while (getline_fn(&scratch_buf, stdin) != EOF) {
|
||||
name_rev_line(scratch_buf.buf, &cmd);
|
||||
/*
|
||||
* We do not pass on the terminator to name_rev_line,
|
||||
* unlike name-rev.
|
||||
*/
|
||||
printf("%c", output_terminator);
|
||||
maybe_flush_or_die(stdout, "stdout");
|
||||
}
|
||||
break;
|
||||
case REVS:
|
||||
while (getline_fn(&scratch_buf, stdin) != EOF) {
|
||||
struct object_id oid;
|
||||
struct object *object;
|
||||
struct object *peeled;
|
||||
|
||||
if (repo_get_oid(the_repository, scratch_buf.buf, &oid)) {
|
||||
fprintf(stderr, "Could not get object name for %s. Skipping.\n",
|
||||
scratch_buf.buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
object = parse_object(the_repository, &oid);
|
||||
if (!object) {
|
||||
fprintf(stderr, "Could not get object for %s. Skipping.\n",
|
||||
scratch_buf.buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
peeled = deref_tag(the_repository, object, scratch_buf.buf, 0);
|
||||
if (!peeled || peeled->type != OBJ_COMMIT) {
|
||||
fprintf(stderr,
|
||||
"Could not get commit for %s. Skipping.\n",
|
||||
scratch_buf.buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
get_format_rev((struct commit *)peeled,
|
||||
&format_pp, &scratch_buf);
|
||||
printf("%s%c", scratch_buf.buf, output_terminator);
|
||||
maybe_flush_or_die(stdout, "stdout");
|
||||
strbuf_release(&scratch_buf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG("uncovered case: %d", stdin_mode);
|
||||
}
|
||||
|
||||
strbuf_release(&scratch_buf);
|
||||
string_list_clear(¬es, 0);
|
||||
release_display_notes(&format_notes_opt);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -629,14 +629,21 @@ static off_t write_reuse_object(struct hashfile *f, struct object_entry *entry,
|
|||
struct packed_git *p = IN_PACK(entry);
|
||||
struct pack_window *w_curs = NULL;
|
||||
uint32_t pos;
|
||||
off_t offset;
|
||||
off_t offset, cur;
|
||||
enum object_type type = oe_type(entry);
|
||||
enum object_type in_pack_type;
|
||||
off_t datalen;
|
||||
unsigned char header[MAX_PACK_OBJECT_HEADER],
|
||||
dheader[MAX_PACK_OBJECT_HEADER];
|
||||
unsigned hdrlen;
|
||||
const unsigned hashsz = the_hash_algo->rawsz;
|
||||
unsigned long entry_size = SIZE(entry);
|
||||
size_t entry_size;
|
||||
|
||||
cur = entry->in_pack_offset;
|
||||
in_pack_type = unpack_object_header(p, &w_curs, &cur, &entry_size);
|
||||
if (in_pack_type < 0)
|
||||
die(_("write_reuse_object: unable to parse object header of %s"),
|
||||
oid_to_hex(&entry->idx.oid));
|
||||
|
||||
if (DELTA(entry))
|
||||
type = (allow_ofs_delta && DELTA(entry)->idx.offset) ?
|
||||
|
|
@ -664,7 +671,8 @@ static off_t write_reuse_object(struct hashfile *f, struct object_entry *entry,
|
|||
datalen -= entry->in_pack_header_size;
|
||||
|
||||
if (!pack_to_stdout && p->index_version == 1 &&
|
||||
check_pack_inflate(p, &w_curs, offset, datalen, entry_size)) {
|
||||
check_pack_inflate(p, &w_curs, offset, datalen,
|
||||
cast_size_t_to_ulong(entry_size))) {
|
||||
error(_("corrupt packed object for %s"),
|
||||
oid_to_hex(&entry->idx.oid));
|
||||
unuse_pack(&w_curs);
|
||||
|
|
@ -1087,7 +1095,7 @@ static void write_reused_pack_one(struct packed_git *reuse_packfile,
|
|||
{
|
||||
off_t offset, next, cur;
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
size_t size;
|
||||
|
||||
offset = pack_pos_to_offset(reuse_packfile, pos);
|
||||
next = pack_pos_to_offset(reuse_packfile, pos + 1);
|
||||
|
|
@ -2243,7 +2251,7 @@ static void check_object(struct object_entry *entry, uint32_t object_index)
|
|||
off_t ofs;
|
||||
unsigned char *buf, c;
|
||||
enum object_type type;
|
||||
unsigned long in_pack_size;
|
||||
size_t in_pack_size;
|
||||
|
||||
buf = use_pack(p, &w_curs, entry->in_pack_offset, &avail);
|
||||
|
||||
|
|
@ -2270,7 +2278,7 @@ static void check_object(struct object_entry *entry, uint32_t object_index)
|
|||
default:
|
||||
/* Not a delta hence we've already got all we need. */
|
||||
oe_set_type(entry, entry->in_pack_type);
|
||||
SET_SIZE(entry, in_pack_size);
|
||||
SET_SIZE(entry, cast_size_t_to_ulong(in_pack_size));
|
||||
entry->in_pack_header_size = used;
|
||||
if (oe_type(entry) < OBJ_COMMIT || oe_type(entry) > OBJ_BLOB)
|
||||
goto give_up;
|
||||
|
|
@ -2324,8 +2332,8 @@ static void check_object(struct object_entry *entry, uint32_t object_index)
|
|||
if (have_base &&
|
||||
can_reuse_delta(&base_ref, entry, &base_entry)) {
|
||||
oe_set_type(entry, entry->in_pack_type);
|
||||
SET_SIZE(entry, in_pack_size); /* delta size */
|
||||
SET_DELTA_SIZE(entry, in_pack_size);
|
||||
SET_SIZE(entry, cast_size_t_to_ulong(in_pack_size)); /* delta size */
|
||||
SET_DELTA_SIZE(entry, cast_size_t_to_ulong(in_pack_size));
|
||||
|
||||
if (base_entry) {
|
||||
SET_DELTA(entry, base_entry);
|
||||
|
|
@ -2734,16 +2742,18 @@ unsigned long oe_get_size_slow(struct packing_data *pack,
|
|||
struct pack_window *w_curs;
|
||||
unsigned char *buf;
|
||||
enum object_type type;
|
||||
unsigned long used, avail, size;
|
||||
unsigned long used, avail;
|
||||
size_t size;
|
||||
|
||||
if (e->type_ != OBJ_OFS_DELTA && e->type_ != OBJ_REF_DELTA) {
|
||||
unsigned long sz;
|
||||
packing_data_lock(&to_pack);
|
||||
if (odb_read_object_info(the_repository->objects,
|
||||
&e->idx.oid, &size) < 0)
|
||||
&e->idx.oid, &sz) < 0)
|
||||
die(_("unable to get size of %s"),
|
||||
oid_to_hex(&e->idx.oid));
|
||||
packing_data_unlock(&to_pack);
|
||||
return size;
|
||||
return sz;
|
||||
}
|
||||
|
||||
p = oe_in_pack(pack, e);
|
||||
|
|
@ -2760,7 +2770,7 @@ unsigned long oe_get_size_slow(struct packing_data *pack,
|
|||
|
||||
unuse_pack(&w_curs);
|
||||
packing_data_unlock(&to_pack);
|
||||
return size;
|
||||
return cast_size_t_to_ulong(size);
|
||||
}
|
||||
|
||||
static int try_delta(struct unpacked *trg, struct unpacked *src,
|
||||
|
|
@ -4265,6 +4275,7 @@ static void enumerate_and_traverse_cruft_objects(struct string_list *fresh_packs
|
|||
traverse_commit_list(&revs, show_cruft_commit, show_cruft_object, NULL);
|
||||
|
||||
stop_progress(&progress_state);
|
||||
release_revisions(&revs);
|
||||
}
|
||||
|
||||
static void read_cruft_objects(void)
|
||||
|
|
|
|||
|
|
@ -996,9 +996,13 @@ int cmd_pull(int argc,
|
|||
OPT_PASSTHRU('6', "ipv6", &opt_ipv6, NULL,
|
||||
N_("use IPv6 addresses only"),
|
||||
PARSE_OPT_NOARG),
|
||||
OPT_PASSTHRU_ARGV(0, "negotiation-tip", &opt_fetch, N_("revision"),
|
||||
OPT_PASSTHRU_ARGV(0, "negotiation-restrict", &opt_fetch, N_("revision"),
|
||||
N_("report that we have only objects reachable from this object"),
|
||||
0),
|
||||
OPT_ALIAS(0, "negotiation-tip", "negotiation-restrict"),
|
||||
OPT_PASSTHRU_ARGV(0, "negotiation-include", &opt_fetch, N_("revision"),
|
||||
N_("ensure this ref is always sent as a negotiation have"),
|
||||
0),
|
||||
OPT_BOOL(0, "show-forced-updates", &opt_show_forced_updates,
|
||||
N_("check for forced-updates on all updated branches")),
|
||||
OPT_PASSTHRU(0, "set-upstream", &set_upstream, NULL,
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ int cmd_read_tree(int argc,
|
|||
opts.preserve_ignored = 0;
|
||||
/* otherwise, opts.preserve_ignored is irrelevant */
|
||||
if (opts.merge && !opts.index_only)
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
|
||||
if (opts.skip_sparse_checkout)
|
||||
ensure_full_index(the_repository->index);
|
||||
|
|
|
|||
|
|
@ -1456,7 +1456,8 @@ static const char *push_to_checkout(unsigned char *hash,
|
|||
struct strvec *env,
|
||||
const char *work_tree)
|
||||
{
|
||||
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
|
||||
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT_FORCE_SERIAL;
|
||||
|
||||
opt.invoked_hook = invoked_hook;
|
||||
|
||||
strvec_pushf(env, "GIT_WORK_TREE=%s", absolute_path(work_tree));
|
||||
|
|
@ -1641,8 +1642,8 @@ static const char *update(struct command *cmd, struct shallow_info *si)
|
|||
ret = NULL; /* good */
|
||||
}
|
||||
strbuf_release(&err);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
enum ref_transaction_error tx_err;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
if (shallow_update && si->shallow_ref[cmd->index] &&
|
||||
update_shallow_ref(cmd, si)) {
|
||||
|
|
@ -1650,14 +1651,18 @@ static const char *update(struct command *cmd, struct shallow_info *si)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (ref_transaction_update(transaction,
|
||||
namespaced_name,
|
||||
new_oid, old_oid,
|
||||
NULL, NULL,
|
||||
0, "push",
|
||||
&err)) {
|
||||
tx_err = ref_transaction_update(transaction,
|
||||
namespaced_name,
|
||||
new_oid, old_oid,
|
||||
NULL, NULL,
|
||||
0, "push",
|
||||
&err);
|
||||
if (tx_err) {
|
||||
rp_error("%s", err.buf);
|
||||
ret = "failed to update ref";
|
||||
if (tx_err == REF_TRANSACTION_ERROR_GENERIC)
|
||||
ret = "failed to update ref";
|
||||
else
|
||||
ret = ref_transaction_error_msg(tx_err);
|
||||
} else {
|
||||
ret = NULL; /* good */
|
||||
}
|
||||
|
|
@ -2642,7 +2647,7 @@ int cmd_receive_pack(int argc,
|
|||
|
||||
setup_path();
|
||||
|
||||
if (!enter_repo(service_dir, 0))
|
||||
if (!enter_repo(the_repository, service_dir, 0))
|
||||
die("'%s' does not appear to be a git repository", service_dir);
|
||||
|
||||
repo_config(the_repository, receive_pack_config, NULL);
|
||||
|
|
|
|||
102
builtin/repack.c
102
builtin/repack.c
|
|
@ -33,7 +33,7 @@ static int midx_must_contain_cruft = 1;
|
|||
static const char *const git_repack_usage[] = {
|
||||
N_("git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n"
|
||||
"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n"
|
||||
"[--write-midx] [--name-hash-version=<n>] [--path-walk]"),
|
||||
"[--write-midx[=<mode>]] [--name-hash-version=<n>] [--path-walk]"),
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -42,9 +42,14 @@ static const char incremental_bitmap_conflict_error[] = N_(
|
|||
"--no-write-bitmap-index or disable the pack.writeBitmaps configuration."
|
||||
);
|
||||
|
||||
#define DEFAULT_MIDX_SPLIT_FACTOR 2
|
||||
#define DEFAULT_MIDX_NEW_LAYER_THRESHOLD 8
|
||||
|
||||
struct repack_config_ctx {
|
||||
struct pack_objects_args *po_args;
|
||||
struct pack_objects_args *cruft_po_args;
|
||||
int midx_split_factor;
|
||||
int midx_new_layer_threshold;
|
||||
};
|
||||
|
||||
static int repack_config(const char *var, const char *value,
|
||||
|
|
@ -94,9 +99,39 @@ static int repack_config(const char *var, const char *value,
|
|||
midx_must_contain_cruft = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "repack.midxsplitfactor")) {
|
||||
repack_ctx->midx_split_factor = git_config_int(var, value,
|
||||
ctx->kvi);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "repack.midxnewlayerthreshold")) {
|
||||
repack_ctx->midx_new_layer_threshold = git_config_int(var, value,
|
||||
ctx->kvi);
|
||||
return 0;
|
||||
}
|
||||
return git_default_config(var, value, ctx, cb);
|
||||
}
|
||||
|
||||
static int option_parse_write_midx(const struct option *opt, const char *arg,
|
||||
int unset)
|
||||
{
|
||||
enum repack_write_midx_mode *cfg = opt->value;
|
||||
|
||||
if (unset) {
|
||||
*cfg = REPACK_WRITE_MIDX_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!arg || !*arg)
|
||||
*cfg = REPACK_WRITE_MIDX_DEFAULT;
|
||||
else if (!strcmp(arg, "incremental"))
|
||||
*cfg = REPACK_WRITE_MIDX_INCREMENTAL;
|
||||
else
|
||||
return error(_("unknown value for %s: %s"), opt->long_name, arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_repack(int argc,
|
||||
const char **argv,
|
||||
const char *prefix,
|
||||
|
|
@ -119,7 +154,7 @@ int cmd_repack(int argc,
|
|||
struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
|
||||
struct pack_objects_args po_args = PACK_OBJECTS_ARGS_INIT;
|
||||
struct pack_objects_args cruft_po_args = PACK_OBJECTS_ARGS_INIT;
|
||||
int write_midx = 0;
|
||||
enum repack_write_midx_mode write_midx = REPACK_WRITE_MIDX_NONE;
|
||||
const char *cruft_expiration = NULL;
|
||||
const char *expire_to = NULL;
|
||||
const char *filter_to = NULL;
|
||||
|
|
@ -185,8 +220,14 @@ int cmd_repack(int argc,
|
|||
N_("do not repack this pack")),
|
||||
OPT_INTEGER('g', "geometric", &geometry.split_factor,
|
||||
N_("find a geometric progression with factor <N>")),
|
||||
OPT_BOOL('m', "write-midx", &write_midx,
|
||||
N_("write a multi-pack index of the resulting packs")),
|
||||
OPT_CALLBACK_F(0, "write-midx", &write_midx,
|
||||
N_("mode"),
|
||||
N_("write a multi-pack index of the resulting packs"),
|
||||
PARSE_OPT_OPTARG, option_parse_write_midx),
|
||||
OPT_SET_INT_F('m', NULL, &write_midx,
|
||||
N_("write a multi-pack index of the resulting packs"),
|
||||
REPACK_WRITE_MIDX_DEFAULT,
|
||||
PARSE_OPT_HIDDEN),
|
||||
OPT_STRING(0, "expire-to", &expire_to, N_("dir"),
|
||||
N_("pack prefix to store a pack containing pruned objects")),
|
||||
OPT_STRING(0, "filter-to", &filter_to, N_("dir"),
|
||||
|
|
@ -199,6 +240,8 @@ int cmd_repack(int argc,
|
|||
memset(&config_ctx, 0, sizeof(config_ctx));
|
||||
config_ctx.po_args = &po_args;
|
||||
config_ctx.cruft_po_args = &cruft_po_args;
|
||||
config_ctx.midx_split_factor = DEFAULT_MIDX_SPLIT_FACTOR;
|
||||
config_ctx.midx_new_layer_threshold = DEFAULT_MIDX_NEW_LAYER_THRESHOLD;
|
||||
|
||||
repo_config(repo, repack_config, &config_ctx);
|
||||
|
||||
|
|
@ -221,14 +264,16 @@ int cmd_repack(int argc,
|
|||
pack_everything |= ALL_INTO_ONE;
|
||||
|
||||
if (write_bitmaps < 0) {
|
||||
if (!write_midx &&
|
||||
if (write_midx == REPACK_WRITE_MIDX_NONE &&
|
||||
(!(pack_everything & ALL_INTO_ONE) || !is_bare_repository()))
|
||||
write_bitmaps = 0;
|
||||
}
|
||||
if (po_args.pack_kept_objects < 0)
|
||||
po_args.pack_kept_objects = write_bitmaps > 0 && !write_midx;
|
||||
po_args.pack_kept_objects = write_bitmaps > 0 &&
|
||||
write_midx == REPACK_WRITE_MIDX_NONE;
|
||||
|
||||
if (write_bitmaps && !(pack_everything & ALL_INTO_ONE) && !write_midx)
|
||||
if (write_bitmaps && !(pack_everything & ALL_INTO_ONE) &&
|
||||
write_midx == REPACK_WRITE_MIDX_NONE)
|
||||
die(_(incremental_bitmap_conflict_error));
|
||||
|
||||
if (write_bitmaps && po_args.local &&
|
||||
|
|
@ -244,7 +289,14 @@ int cmd_repack(int argc,
|
|||
write_bitmaps = 0;
|
||||
}
|
||||
|
||||
if (write_midx && write_bitmaps) {
|
||||
if (config_ctx.midx_split_factor < 2)
|
||||
die(_("invalid value for %s: %d"), "--midx-split-factor",
|
||||
config_ctx.midx_split_factor);
|
||||
if (config_ctx.midx_new_layer_threshold < 1)
|
||||
die(_("invalid value for %s: %d"), "--midx-new-layer-threshold",
|
||||
config_ctx.midx_new_layer_threshold);
|
||||
|
||||
if (write_midx != REPACK_WRITE_MIDX_NONE && write_bitmaps) {
|
||||
struct strbuf path = STRBUF_INIT;
|
||||
|
||||
strbuf_addf(&path, "%s/%s_XXXXXX",
|
||||
|
|
@ -267,6 +319,10 @@ int cmd_repack(int argc,
|
|||
if (geometry.split_factor) {
|
||||
if (pack_everything)
|
||||
die(_("options '%s' and '%s' cannot be used together"), "--geometric", "-A/-a");
|
||||
if (write_midx == REPACK_WRITE_MIDX_INCREMENTAL) {
|
||||
geometry.midx_layer_threshold = config_ctx.midx_new_layer_threshold;
|
||||
geometry.midx_layer_threshold_set = true;
|
||||
}
|
||||
pack_geometry_init(&geometry, &existing, &po_args);
|
||||
pack_geometry_split(&geometry);
|
||||
}
|
||||
|
|
@ -297,7 +353,7 @@ int cmd_repack(int argc,
|
|||
}
|
||||
if (repo_has_promisor_remote(repo))
|
||||
strvec_push(&cmd.args, "--exclude-promisor-objects");
|
||||
if (!write_midx) {
|
||||
if (write_midx == REPACK_WRITE_MIDX_NONE) {
|
||||
if (write_bitmaps > 0)
|
||||
strvec_push(&cmd.args, "--write-bitmap-index");
|
||||
else if (write_bitmaps < 0)
|
||||
|
|
@ -417,7 +473,7 @@ int cmd_repack(int argc,
|
|||
* midx_has_unknown_packs() will make the decision for
|
||||
* us.
|
||||
*/
|
||||
if (!get_multi_pack_index(repo->objects->sources))
|
||||
if (!get_multi_pack_index(existing.source))
|
||||
midx_must_contain_cruft = 1;
|
||||
}
|
||||
|
||||
|
|
@ -516,10 +572,13 @@ int cmd_repack(int argc,
|
|||
packtmp);
|
||||
/* End of pack replacement. */
|
||||
|
||||
if (delete_redundant && pack_everything & ALL_INTO_ONE)
|
||||
if (delete_redundant && pack_everything & ALL_INTO_ONE) {
|
||||
if (write_midx == REPACK_WRITE_MIDX_INCREMENTAL)
|
||||
existing_packs_retain_midx_packs(&existing);
|
||||
existing_packs_mark_for_deletion(&existing, &names);
|
||||
}
|
||||
|
||||
if (write_midx) {
|
||||
if (write_midx != REPACK_WRITE_MIDX_NONE) {
|
||||
struct repack_write_midx_opts opts = {
|
||||
.existing = &existing,
|
||||
.geometry = &geometry,
|
||||
|
|
@ -528,11 +587,13 @@ int cmd_repack(int argc,
|
|||
.packdir = packdir,
|
||||
.show_progress = show_progress,
|
||||
.write_bitmaps = write_bitmaps > 0,
|
||||
.midx_must_contain_cruft = midx_must_contain_cruft
|
||||
.midx_must_contain_cruft = midx_must_contain_cruft,
|
||||
.midx_split_factor = config_ctx.midx_split_factor,
|
||||
.midx_new_layer_threshold = config_ctx.midx_new_layer_threshold,
|
||||
.mode = write_midx,
|
||||
};
|
||||
|
||||
ret = write_midx_included_packs(&opts);
|
||||
|
||||
ret = repack_write_midx(&opts);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
@ -541,11 +602,15 @@ int cmd_repack(int argc,
|
|||
|
||||
if (delete_redundant) {
|
||||
int opts = 0;
|
||||
existing_packs_remove_redundant(&existing, packdir);
|
||||
bool wrote_incremental_midx = write_midx == REPACK_WRITE_MIDX_INCREMENTAL;
|
||||
|
||||
existing_packs_remove_redundant(&existing, packdir,
|
||||
wrote_incremental_midx);
|
||||
|
||||
if (geometry.split_factor)
|
||||
pack_geometry_remove_redundant(&geometry, &names,
|
||||
&existing, packdir);
|
||||
&existing, packdir,
|
||||
wrote_incremental_midx);
|
||||
if (show_progress)
|
||||
opts |= PRUNE_PACKED_VERBOSE;
|
||||
prune_packed_objects(opts);
|
||||
|
|
@ -564,8 +629,7 @@ int cmd_repack(int argc,
|
|||
unsigned flags = 0;
|
||||
if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL, 0))
|
||||
flags |= MIDX_WRITE_INCREMENTAL;
|
||||
write_midx_file(repo->objects->sources,
|
||||
NULL, NULL, flags);
|
||||
write_midx_file(existing.source, NULL, NULL, flags);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
|
|
|||
|
|
@ -281,11 +281,11 @@ static void parse_args(struct pathspec *pathspec,
|
|||
* Ok, argv[0] looks like a commit/tree; it should not
|
||||
* be a filename.
|
||||
*/
|
||||
verify_non_filename(prefix, argv[0]);
|
||||
verify_non_filename(the_repository, prefix, argv[0]);
|
||||
rev = *argv++;
|
||||
} else {
|
||||
/* Otherwise we treat this as a filename */
|
||||
verify_filename(prefix, argv[0], 1);
|
||||
verify_filename(the_repository, prefix, argv[0], 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -468,7 +468,7 @@ int cmd_reset(int argc,
|
|||
trace2_cmd_mode(reset_type_names[reset_type]);
|
||||
|
||||
if (reset_type != SOFT && (reset_type != MIXED || repo_get_work_tree(the_repository)))
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
|
||||
if (reset_type == MIXED && is_bare_repository())
|
||||
die(_("%s reset is not allowed in a bare repository"),
|
||||
|
|
|
|||
|
|
@ -739,7 +739,7 @@ int cmd_rev_parse(int argc,
|
|||
|
||||
/* No options; just report on whether we're in a git repo or not. */
|
||||
if (argc == 1) {
|
||||
setup_git_directory();
|
||||
setup_git_directory(the_repository);
|
||||
repo_config(the_repository, git_default_config, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -749,7 +749,7 @@ int cmd_rev_parse(int argc,
|
|||
|
||||
if (as_is) {
|
||||
if (show_file(arg, output_prefix) && as_is < 2)
|
||||
verify_filename(prefix, arg, 0);
|
||||
verify_filename(the_repository, prefix, arg, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -774,7 +774,7 @@ int cmd_rev_parse(int argc,
|
|||
|
||||
/* The rest of the options require a git repository. */
|
||||
if (!did_repo_setup) {
|
||||
prefix = setup_git_directory();
|
||||
prefix = setup_git_directory(the_repository);
|
||||
repo_config(the_repository, git_default_config, NULL);
|
||||
did_repo_setup = 1;
|
||||
|
||||
|
|
@ -1006,7 +1006,7 @@ int cmd_rev_parse(int argc,
|
|||
}
|
||||
if (!strcmp(arg, "--show-cdup")) {
|
||||
const char *pfx = prefix;
|
||||
if (!is_inside_work_tree()) {
|
||||
if (!is_inside_work_tree(the_repository)) {
|
||||
const char *work_tree =
|
||||
repo_get_work_tree(the_repository);
|
||||
if (work_tree)
|
||||
|
|
@ -1063,12 +1063,12 @@ int cmd_rev_parse(int argc,
|
|||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--is-inside-git-dir")) {
|
||||
printf("%s\n", is_inside_git_dir() ? "true"
|
||||
printf("%s\n", is_inside_git_dir(the_repository) ? "true"
|
||||
: "false");
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--is-inside-work-tree")) {
|
||||
printf("%s\n", is_inside_work_tree() ? "true"
|
||||
printf("%s\n", is_inside_work_tree(the_repository) ? "true"
|
||||
: "false");
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1173,7 +1173,7 @@ int cmd_rev_parse(int argc,
|
|||
as_is = 1;
|
||||
if (!show_file(arg, output_prefix))
|
||||
continue;
|
||||
verify_filename(prefix, arg, 1);
|
||||
verify_filename(the_repository, prefix, arg, 1);
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
if (verify) {
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ int cmd_rm(int argc,
|
|||
die(_("No pathspec was given. Which files should I remove?"));
|
||||
|
||||
if (!index_only)
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
|
||||
prepare_repo_settings(the_repository);
|
||||
the_repository->settings.command_requires_full_index = 0;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,
|
|||
int res;
|
||||
struct repo_config_values *cfg = repo_config_values(the_repository);
|
||||
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
if (!cfg->apply_sparse_checkout)
|
||||
die(_("this worktree is not sparse"));
|
||||
|
||||
|
|
@ -229,7 +229,7 @@ static int update_working_directory(struct repository *r,
|
|||
o.dst_index = r->index;
|
||||
o.skip_sparse_checkout = 0;
|
||||
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
|
||||
repo_hold_locked_index(r, &lock_file, LOCK_DIE_ON_ERROR);
|
||||
|
||||
|
|
@ -468,7 +468,7 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix,
|
|||
OPT_END(),
|
||||
};
|
||||
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
repo_read_index(repo);
|
||||
|
||||
init_opts.cone_mode = -1;
|
||||
|
|
@ -735,7 +735,8 @@ static void sanitize_paths(struct repository *repo,
|
|||
int prefix_len = strlen(prefix);
|
||||
|
||||
for (i = 0; i < args->nr; i++) {
|
||||
char *prefixed_path = prefix_path(prefix, prefix_len, args->v[i]);
|
||||
char *prefixed_path = prefix_path(the_repository, prefix,
|
||||
prefix_len, args->v[i]);
|
||||
strvec_replace(args, i, prefixed_path);
|
||||
free(prefixed_path);
|
||||
}
|
||||
|
|
@ -801,7 +802,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,
|
|||
int ret;
|
||||
struct repo_config_values *cfg = repo_config_values(the_repository);
|
||||
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
if (!cfg->apply_sparse_checkout)
|
||||
die(_("no sparse-checkout to add to"));
|
||||
|
||||
|
|
@ -855,7 +856,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix,
|
|||
struct strvec patterns = STRVEC_INIT;
|
||||
int ret;
|
||||
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
repo_read_index(repo);
|
||||
|
||||
set_opts.cone_mode = -1;
|
||||
|
|
@ -911,7 +912,7 @@ static int sparse_checkout_reapply(int argc, const char **argv,
|
|||
};
|
||||
struct repo_config_values *cfg = repo_config_values(the_repository);
|
||||
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
if (!cfg->apply_sparse_checkout)
|
||||
die(_("must be in a sparse-checkout to reapply sparsity patterns"));
|
||||
|
||||
|
|
@ -974,7 +975,7 @@ static int sparse_checkout_clean(int argc, const char **argv,
|
|||
OPT_END(),
|
||||
};
|
||||
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
if (!cfg->apply_sparse_checkout)
|
||||
die(_("must be in a sparse-checkout to clean directories"));
|
||||
if (!core_sparse_checkout_cone)
|
||||
|
|
@ -1052,7 +1053,7 @@ static int sparse_checkout_disable(int argc, const char **argv,
|
|||
* forcibly return to a dense checkout regardless of initial state.
|
||||
*/
|
||||
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
argc = parse_options(argc, argv, prefix,
|
||||
builtin_sparse_checkout_disable_options,
|
||||
builtin_sparse_checkout_disable_usage, 0);
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
#define BUILTIN_STASH_POP_USAGE \
|
||||
N_("git stash pop [--index] [-q | --quiet] [<stash>]")
|
||||
#define BUILTIN_STASH_APPLY_USAGE \
|
||||
N_("git stash apply [--index] [-q | --quiet] [<stash>]")
|
||||
N_("git stash apply [--index] [-q | --quiet] [--label-ours=<label>] [--label-theirs=<label>] [--label-base=<label>] [<stash>]")
|
||||
#define BUILTIN_STASH_BRANCH_USAGE \
|
||||
N_("git stash branch <branchname> [<stash>]")
|
||||
#define BUILTIN_STASH_STORE_USAGE \
|
||||
|
|
@ -591,7 +591,9 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
|
|||
}
|
||||
|
||||
static int do_apply_stash(const char *prefix, struct stash_info *info,
|
||||
int index, int quiet)
|
||||
int index, int quiet,
|
||||
const char *label_ours, const char *label_theirs,
|
||||
const char *label_base)
|
||||
{
|
||||
int clean, ret;
|
||||
int has_index = index;
|
||||
|
|
@ -643,9 +645,9 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
|
|||
|
||||
init_ui_merge_options(&o, the_repository);
|
||||
|
||||
o.branch1 = "Updated upstream";
|
||||
o.branch2 = "Stashed changes";
|
||||
o.ancestor = "Stash base";
|
||||
o.branch1 = label_ours ? label_ours : "Updated upstream";
|
||||
o.branch2 = label_theirs ? label_theirs : "Stashed changes";
|
||||
o.ancestor = label_base ? label_base : "Stash base";
|
||||
|
||||
if (oideq(&info->b_tree, &c_tree))
|
||||
o.branch1 = "Version stash was based on";
|
||||
|
|
@ -723,11 +725,18 @@ static int apply_stash(int argc, const char **argv, const char *prefix,
|
|||
int ret = -1;
|
||||
int quiet = 0;
|
||||
int index = use_index;
|
||||
const char *label_ours = NULL, *label_theirs = NULL, *label_base = NULL;
|
||||
struct stash_info info = STASH_INFO_INIT;
|
||||
struct option options[] = {
|
||||
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
|
||||
OPT_BOOL(0, "index", &index,
|
||||
N_("attempt to recreate the index")),
|
||||
OPT_STRING(0, "label-ours", &label_ours, N_("label"),
|
||||
N_("label for the upstream side in conflict markers")),
|
||||
OPT_STRING(0, "label-theirs", &label_theirs, N_("label"),
|
||||
N_("label for the stashed side in conflict markers")),
|
||||
OPT_STRING(0, "label-base", &label_base, N_("label"),
|
||||
N_("label for the base in diff3 conflict markers")),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
|
@ -737,7 +746,8 @@ static int apply_stash(int argc, const char **argv, const char *prefix,
|
|||
if (get_stash_info(&info, argc, argv))
|
||||
goto cleanup;
|
||||
|
||||
ret = do_apply_stash(prefix, &info, index, quiet);
|
||||
ret = do_apply_stash(prefix, &info, index, quiet,
|
||||
label_ours, label_theirs, label_base);
|
||||
cleanup:
|
||||
free_stash_info(&info);
|
||||
return ret;
|
||||
|
|
@ -836,7 +846,8 @@ static int pop_stash(int argc, const char **argv, const char *prefix,
|
|||
if (get_stash_info_assert(&info, argc, argv))
|
||||
goto cleanup;
|
||||
|
||||
if ((ret = do_apply_stash(prefix, &info, index, quiet)))
|
||||
if ((ret = do_apply_stash(prefix, &info, index, quiet,
|
||||
NULL, NULL, NULL)))
|
||||
printf_ln(_("The stash entry is kept in case "
|
||||
"you need it again."));
|
||||
else
|
||||
|
|
@ -877,7 +888,8 @@ static int branch_stash(int argc, const char **argv, const char *prefix,
|
|||
strvec_push(&cp.args, oid_to_hex(&info.b_commit));
|
||||
ret = run_command(&cp);
|
||||
if (!ret)
|
||||
ret = do_apply_stash(prefix, &info, 1, 0);
|
||||
ret = do_apply_stash(prefix, &info, 1, 0,
|
||||
NULL, NULL, NULL);
|
||||
if (!ret && info.is_stash_ref)
|
||||
ret = do_drop_stash(&info, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ int cmd_stripspace(int argc,
|
|||
usage_with_options(stripspace_usage, options);
|
||||
|
||||
if (mode == STRIP_COMMENTS || mode == COMMENT_LINES) {
|
||||
setup_git_directory_gently(&nongit);
|
||||
setup_git_directory_gently(the_repository, &nongit);
|
||||
repo_config(the_repository, git_default_config, NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1250,7 +1250,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
|
|||
|
||||
if (!info->cached) {
|
||||
if (diff_cmd == DIFF_INDEX)
|
||||
setup_work_tree();
|
||||
setup_work_tree(the_repository);
|
||||
if (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0) {
|
||||
perror("repo_read_index_preload");
|
||||
ret = -1;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue