Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
82689d5e5d | |||
16128765d7 | |||
b7b37a3371 | |||
6662a836eb | |||
3305300f4c | |||
304a50adff | |||
f930a23943 | |||
81c2d4c3a5 | |||
937b71cc8b | |||
17d23e8a38 | |||
522cc87fdc | |||
48050c42c7 | |||
1de69c0cdd | |||
f6e0b9f389 | |||
b49f309aa1 | |||
81dc898df9 | |||
a244dc5b0a | |||
3c50032ff5 | |||
dfa6b32b5e | |||
d74b1fd54f | |||
a60a66e409 | |||
e1e12e97ac | |||
447ac906e1 | |||
34ace8bad0 | |||
2455720950 | |||
8d0d48cf21 | |||
eb22e7dfa2 |
5
.github/workflows/main.yml
vendored
5
.github/workflows/main.yml
vendored
@ -186,11 +186,6 @@ jobs:
|
|||||||
## Unzip and remove the artifact
|
## Unzip and remove the artifact
|
||||||
unzip artifacts.zip
|
unzip artifacts.zip
|
||||||
rm artifacts.zip
|
rm artifacts.zip
|
||||||
- name: initialize vcpkg
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
repository: 'microsoft/vcpkg'
|
|
||||||
path: 'compat/vcbuild/vcpkg'
|
|
||||||
- name: download vcpkg artifacts
|
- name: download vcpkg artifacts
|
||||||
shell: powershell
|
shell: powershell
|
||||||
run: |
|
run: |
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -33,7 +33,6 @@
|
|||||||
/git-check-mailmap
|
/git-check-mailmap
|
||||||
/git-check-ref-format
|
/git-check-ref-format
|
||||||
/git-checkout
|
/git-checkout
|
||||||
/git-checkout--worker
|
|
||||||
/git-checkout-index
|
/git-checkout-index
|
||||||
/git-cherry
|
/git-cherry
|
||||||
/git-cherry-pick
|
/git-cherry-pick
|
||||||
@ -163,7 +162,6 @@
|
|||||||
/git-stripspace
|
/git-stripspace
|
||||||
/git-submodule
|
/git-submodule
|
||||||
/git-submodule--helper
|
/git-submodule--helper
|
||||||
/git-subtree
|
|
||||||
/git-svn
|
/git-svn
|
||||||
/git-switch
|
/git-switch
|
||||||
/git-symbolic-ref
|
/git-symbolic-ref
|
||||||
|
1
.mailmap
1
.mailmap
@ -220,7 +220,6 @@ Philipp A. Hartmann <pah@qo.cx> <ph@sorgh.de>
|
|||||||
Philippe Bruhat <book@cpan.org>
|
Philippe Bruhat <book@cpan.org>
|
||||||
Ralf Thielow <ralf.thielow@gmail.com> <ralf.thielow@googlemail.com>
|
Ralf Thielow <ralf.thielow@gmail.com> <ralf.thielow@googlemail.com>
|
||||||
Ramsay Jones <ramsay@ramsayjones.plus.com> <ramsay@ramsay1.demon.co.uk>
|
Ramsay Jones <ramsay@ramsayjones.plus.com> <ramsay@ramsay1.demon.co.uk>
|
||||||
Ramkumar Ramachandra <r@artagnon.com> <artagnon@gmail.com>
|
|
||||||
Randall S. Becker <randall.becker@nexbridge.ca> <rsbecker@nexbridge.com>
|
Randall S. Becker <randall.becker@nexbridge.ca> <rsbecker@nexbridge.com>
|
||||||
René Scharfe <l.s.r@web.de> <rene.scharfe@lsrfire.ath.cx>
|
René Scharfe <l.s.r@web.de> <rene.scharfe@lsrfire.ath.cx>
|
||||||
René Scharfe <l.s.r@web.de> Rene Scharfe
|
René Scharfe <l.s.r@web.de> Rene Scharfe
|
||||||
|
@ -175,11 +175,6 @@ For shell scripts specifically (not exhaustive):
|
|||||||
|
|
||||||
does not have such a problem.
|
does not have such a problem.
|
||||||
|
|
||||||
- Even though "local" is not part of POSIX, we make heavy use of it
|
|
||||||
in our test suite. We do not use it in scripted Porcelains, and
|
|
||||||
hopefully nobody starts using "local" before they are reimplemented
|
|
||||||
in C ;-)
|
|
||||||
|
|
||||||
|
|
||||||
For C programs:
|
For C programs:
|
||||||
|
|
||||||
@ -503,12 +498,7 @@ Error Messages
|
|||||||
|
|
||||||
- Do not end error messages with a full stop.
|
- Do not end error messages with a full stop.
|
||||||
|
|
||||||
- Do not capitalize the first word, only because it is the first word
|
- Do not capitalize ("unable to open %s", not "Unable to open %s")
|
||||||
in the message ("unable to open %s", not "Unable to open %s"). But
|
|
||||||
"SHA-3 not supported" is fine, because the reason the first word is
|
|
||||||
capitalized is not because it is at the beginning of the sentence,
|
|
||||||
but because the word would be spelled in capital letters even when
|
|
||||||
it appeared in the middle of the sentence.
|
|
||||||
|
|
||||||
- Say what the error is first ("cannot open %s", not "%s: cannot open")
|
- Say what the error is first ("cannot open %s", not "%s: cannot open")
|
||||||
|
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
MAN1_TXT =
|
MAN1_TXT =
|
||||||
MAN5_TXT =
|
MAN5_TXT =
|
||||||
MAN7_TXT =
|
MAN7_TXT =
|
||||||
HOWTO_TXT =
|
|
||||||
DOC_DEP_TXT =
|
|
||||||
TECH_DOCS =
|
TECH_DOCS =
|
||||||
ARTICLES =
|
ARTICLES =
|
||||||
SP_ARTICLES =
|
SP_ARTICLES =
|
||||||
@ -44,11 +42,6 @@ MAN7_TXT += gittutorial-2.txt
|
|||||||
MAN7_TXT += gittutorial.txt
|
MAN7_TXT += gittutorial.txt
|
||||||
MAN7_TXT += gitworkflows.txt
|
MAN7_TXT += gitworkflows.txt
|
||||||
|
|
||||||
HOWTO_TXT += $(wildcard howto/*.txt)
|
|
||||||
|
|
||||||
DOC_DEP_TXT += $(wildcard *.txt)
|
|
||||||
DOC_DEP_TXT += $(wildcard config/*.txt)
|
|
||||||
|
|
||||||
ifdef MAN_FILTER
|
ifdef MAN_FILTER
|
||||||
MAN_TXT = $(filter $(MAN_FILTER),$(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT))
|
MAN_TXT = $(filter $(MAN_FILTER),$(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT))
|
||||||
else
|
else
|
||||||
@ -83,7 +76,6 @@ SP_ARTICLES += howto/rebuild-from-update-hook
|
|||||||
SP_ARTICLES += howto/rebase-from-internal-branch
|
SP_ARTICLES += howto/rebase-from-internal-branch
|
||||||
SP_ARTICLES += howto/keep-canonical-history-correct
|
SP_ARTICLES += howto/keep-canonical-history-correct
|
||||||
SP_ARTICLES += howto/maintain-git
|
SP_ARTICLES += howto/maintain-git
|
||||||
SP_ARTICLES += howto/coordinate-embargoed-releases
|
|
||||||
API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt)))
|
API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt)))
|
||||||
SP_ARTICLES += $(API_DOCS)
|
SP_ARTICLES += $(API_DOCS)
|
||||||
|
|
||||||
@ -98,7 +90,6 @@ TECH_DOCS += technical/multi-pack-index
|
|||||||
TECH_DOCS += technical/pack-format
|
TECH_DOCS += technical/pack-format
|
||||||
TECH_DOCS += technical/pack-heuristics
|
TECH_DOCS += technical/pack-heuristics
|
||||||
TECH_DOCS += technical/pack-protocol
|
TECH_DOCS += technical/pack-protocol
|
||||||
TECH_DOCS += technical/parallel-checkout
|
|
||||||
TECH_DOCS += technical/partial-clone
|
TECH_DOCS += technical/partial-clone
|
||||||
TECH_DOCS += technical/protocol-capabilities
|
TECH_DOCS += technical/protocol-capabilities
|
||||||
TECH_DOCS += technical/protocol-common
|
TECH_DOCS += technical/protocol-common
|
||||||
@ -293,7 +284,7 @@ docdep_prereqs = \
|
|||||||
mergetools-list.made $(mergetools_txt) \
|
mergetools-list.made $(mergetools_txt) \
|
||||||
cmd-list.made $(cmds_txt)
|
cmd-list.made $(cmds_txt)
|
||||||
|
|
||||||
doc.dep : $(docdep_prereqs) $(DOC_DEP_TXT) build-docdep.perl
|
doc.dep : $(docdep_prereqs) $(wildcard *.txt) $(wildcard config/*.txt) build-docdep.perl
|
||||||
$(QUIET_GEN)$(RM) $@+ $@ && \
|
$(QUIET_GEN)$(RM) $@+ $@ && \
|
||||||
$(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \
|
$(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \
|
||||||
mv $@+ $@
|
mv $@+ $@
|
||||||
@ -436,9 +427,9 @@ $(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml
|
|||||||
$(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+ && \
|
$(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+ && \
|
||||||
mv $@+ $@
|
mv $@+ $@
|
||||||
|
|
||||||
howto-index.txt: howto-index.sh $(HOWTO_TXT)
|
howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
|
||||||
$(QUIET_GEN)$(RM) $@+ $@ && \
|
$(QUIET_GEN)$(RM) $@+ $@ && \
|
||||||
'$(SHELL_PATH_SQ)' ./howto-index.sh $(sort $(HOWTO_TXT)) >$@+ && \
|
'$(SHELL_PATH_SQ)' ./howto-index.sh $(sort $(wildcard howto/*.txt)) >$@+ && \
|
||||||
mv $@+ $@
|
mv $@+ $@
|
||||||
|
|
||||||
$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
|
$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
|
||||||
@ -447,7 +438,7 @@ $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
|
|||||||
WEBDOC_DEST = /pub/software/scm/git/docs
|
WEBDOC_DEST = /pub/software/scm/git/docs
|
||||||
|
|
||||||
howto/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../
|
howto/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../
|
||||||
$(patsubst %.txt,%.html,$(HOWTO_TXT)): %.html : %.txt GIT-ASCIIDOCFLAGS
|
$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt GIT-ASCIIDOCFLAGS
|
||||||
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
|
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
|
||||||
sed -e '1,/^$$/d' $< | \
|
sed -e '1,/^$$/d' $< | \
|
||||||
$(TXT_TO_HTML) - >$@+ && \
|
$(TXT_TO_HTML) - >$@+ && \
|
||||||
@ -479,13 +470,7 @@ print-man1:
|
|||||||
@for i in $(MAN1_TXT); do echo $$i; done
|
@for i in $(MAN1_TXT); do echo $$i; done
|
||||||
|
|
||||||
lint-docs::
|
lint-docs::
|
||||||
$(QUIET_LINT)$(PERL_PATH) lint-gitlink.perl \
|
$(QUIET_LINT)$(PERL_PATH) lint-gitlink.perl
|
||||||
$(HOWTO_TXT) $(DOC_DEP_TXT) \
|
|
||||||
--section=1 $(MAN1_TXT) \
|
|
||||||
--section=5 $(MAN5_TXT) \
|
|
||||||
--section=7 $(MAN7_TXT); \
|
|
||||||
$(PERL_PATH) lint-man-end-blurb.perl $(MAN_TXT); \
|
|
||||||
$(PERL_PATH) lint-man-section-order.perl $(MAN_TXT);
|
|
||||||
|
|
||||||
ifeq ($(wildcard po/Makefile),po/Makefile)
|
ifeq ($(wildcard po/Makefile),po/Makefile)
|
||||||
doc-l10n install-l10n::
|
doc-l10n install-l10n::
|
||||||
|
86
Documentation/RelNotes/2.30.7.txt
Normal file
86
Documentation/RelNotes/2.30.7.txt
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
Git v2.30.7 Release Notes
|
||||||
|
=========================
|
||||||
|
|
||||||
|
This release addresses the security issues CVE-2022-41903 and
|
||||||
|
CVE-2022-23521.
|
||||||
|
|
||||||
|
|
||||||
|
Fixes since v2.30.6
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
* CVE-2022-41903:
|
||||||
|
|
||||||
|
git log has the ability to display commits using an arbitrary
|
||||||
|
format with its --format specifiers. This functionality is also
|
||||||
|
exposed to git archive via the export-subst gitattribute.
|
||||||
|
|
||||||
|
When processing the padding operators (e.g., %<(, %<|(, %>(,
|
||||||
|
%>>(, or %><( ), an integer overflow can occur in
|
||||||
|
pretty.c::format_and_pad_commit() where a size_t is improperly
|
||||||
|
stored as an int, and then added as an offset to a subsequent
|
||||||
|
memcpy() call.
|
||||||
|
|
||||||
|
This overflow can be triggered directly by a user running a
|
||||||
|
command which invokes the commit formatting machinery (e.g., git
|
||||||
|
log --format=...). It may also be triggered indirectly through
|
||||||
|
git archive via the export-subst mechanism, which expands format
|
||||||
|
specifiers inside of files within the repository during a git
|
||||||
|
archive.
|
||||||
|
|
||||||
|
This integer overflow can result in arbitrary heap writes, which
|
||||||
|
may result in remote code execution.
|
||||||
|
|
||||||
|
* CVE-2022-23521:
|
||||||
|
|
||||||
|
gitattributes are a mechanism to allow defining attributes for
|
||||||
|
paths. These attributes can be defined by adding a `.gitattributes`
|
||||||
|
file to the repository, which contains a set of file patterns and
|
||||||
|
the attributes that should be set for paths matching this pattern.
|
||||||
|
|
||||||
|
When parsing gitattributes, multiple integer overflows can occur
|
||||||
|
when there is a huge number of path patterns, a huge number of
|
||||||
|
attributes for a single pattern, or when the declared attribute
|
||||||
|
names are huge.
|
||||||
|
|
||||||
|
These overflows can be triggered via a crafted `.gitattributes` file
|
||||||
|
that may be part of the commit history. Git silently splits lines
|
||||||
|
longer than 2KB when parsing gitattributes from a file, but not when
|
||||||
|
parsing them from the index. Consequentially, the failure mode
|
||||||
|
depends on whether the file exists in the working tree, the index or
|
||||||
|
both.
|
||||||
|
|
||||||
|
This integer overflow can result in arbitrary heap reads and writes,
|
||||||
|
which may result in remote code execution.
|
||||||
|
|
||||||
|
Credit for finding CVE-2022-41903 goes to Joern Schneeweisz of GitLab.
|
||||||
|
An initial fix was authored by Markus Vervier of X41 D-Sec. Credit for
|
||||||
|
finding CVE-2022-23521 goes to Markus Vervier and Eric Sesterhenn of X41
|
||||||
|
D-Sec. This work was sponsored by OSTIF.
|
||||||
|
|
||||||
|
The proposed fixes have been polished and extended to cover additional
|
||||||
|
findings by Patrick Steinhardt of GitLab, with help from others on the
|
||||||
|
Git security mailing list.
|
||||||
|
|
||||||
|
Patrick Steinhardt (21):
|
||||||
|
attr: fix overflow when upserting attribute with overly long name
|
||||||
|
attr: fix out-of-bounds read with huge attribute names
|
||||||
|
attr: fix integer overflow when parsing huge attribute names
|
||||||
|
attr: fix out-of-bounds write when parsing huge number of attributes
|
||||||
|
attr: fix out-of-bounds read with unreasonable amount of patterns
|
||||||
|
attr: fix integer overflow with more than INT_MAX macros
|
||||||
|
attr: harden allocation against integer overflows
|
||||||
|
attr: fix silently splitting up lines longer than 2048 bytes
|
||||||
|
attr: ignore attribute lines exceeding 2048 bytes
|
||||||
|
attr: ignore overly large gitattributes files
|
||||||
|
pretty: fix out-of-bounds write caused by integer overflow
|
||||||
|
pretty: fix out-of-bounds read when left-flushing with stealing
|
||||||
|
pretty: fix out-of-bounds read when parsing invalid padding format
|
||||||
|
pretty: fix adding linefeed when placeholder is not expanded
|
||||||
|
pretty: fix integer overflow in wrapping format
|
||||||
|
utf8: fix truncated string lengths in `utf8_strnwidth()`
|
||||||
|
utf8: fix returning negative string width
|
||||||
|
utf8: fix overflow when returning string width
|
||||||
|
utf8: fix checking for glyph width in `strbuf_utf8_replace()`
|
||||||
|
utf8: refactor `strbuf_utf8_replace` to not rely on preallocated buffer
|
||||||
|
pretty: restrict input lengths for padding and wrapping formats
|
||||||
|
|
5
Documentation/RelNotes/2.31.6.txt
Normal file
5
Documentation/RelNotes/2.31.6.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Git v2.31.6 Release Notes
|
||||||
|
=========================
|
||||||
|
|
||||||
|
This release merges the security fix that appears in v2.30.7; see
|
||||||
|
the release notes for that version for details.
|
@ -1,416 +0,0 @@
|
|||||||
Git 2.32 Release Notes
|
|
||||||
======================
|
|
||||||
|
|
||||||
Backward compatibility notes
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
* ".gitattributes", ".gitignore", and ".mailmap" files that are
|
|
||||||
symbolic links are ignored.
|
|
||||||
|
|
||||||
* "git apply --3way" used to first attempt a straight application,
|
|
||||||
and only fell back to the 3-way merge algorithm when the stright
|
|
||||||
application failed. Starting with this version, the command will
|
|
||||||
first try the 3-way merge algorithm and only when it fails (either
|
|
||||||
resulting with conflict or the base versions of blobs are missing),
|
|
||||||
falls back to the usual patch application.
|
|
||||||
|
|
||||||
|
|
||||||
Updates since v2.31
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
UI, Workflows & Features
|
|
||||||
|
|
||||||
* It does not make sense to make ".gitattributes", ".gitignore" and
|
|
||||||
".mailmap" symlinks, as they are supposed to be usable from the
|
|
||||||
object store (think: bare repositories where HEAD:.mailmap etc. are
|
|
||||||
used). When these files are symbolic links, we used to read the
|
|
||||||
contents of the files pointed by them by mistake, which has been
|
|
||||||
corrected.
|
|
||||||
|
|
||||||
* "git stash show" learned to optionally show untracked part of the
|
|
||||||
stash.
|
|
||||||
|
|
||||||
* "git log --format='...'" learned "%(describe)" placeholder.
|
|
||||||
|
|
||||||
* "git repack" so far has been only capable of repacking everything
|
|
||||||
under the sun into a single pack (or split by size). A cleverer
|
|
||||||
strategy to reduce the cost of repacking a repository has been
|
|
||||||
introduced.
|
|
||||||
|
|
||||||
* The http codepath learned to let the credential layer to cache the
|
|
||||||
password used to unlock a certificate that has successfully been
|
|
||||||
used.
|
|
||||||
|
|
||||||
* "git commit --fixup=<commit>", which was to tweak the changes made
|
|
||||||
to the contents while keeping the original log message intact,
|
|
||||||
learned "--fixup=(amend|reword):<commit>", that can be used to
|
|
||||||
tweak both the message and the contents, and only the message,
|
|
||||||
respectively.
|
|
||||||
|
|
||||||
* "git send-email" learned to honor the core.hooksPath configuration.
|
|
||||||
|
|
||||||
* "git format-patch -v<n>" learned to allow a reroll count that is
|
|
||||||
not an integer.
|
|
||||||
|
|
||||||
* "git commit" learned "--trailer <key>[=<value>]" option; together
|
|
||||||
with the interpret-trailers command, this will make it easier to
|
|
||||||
support custom trailers.
|
|
||||||
|
|
||||||
* "git clone --reject-shallow" option fails the clone as soon as we
|
|
||||||
notice that we are cloning from a shallow repository.
|
|
||||||
|
|
||||||
* A configuration variable has been added to force tips of certain
|
|
||||||
refs to be given a reachability bitmap.
|
|
||||||
|
|
||||||
* "gitweb" learned "e-mail privacy" feature to redact strings that
|
|
||||||
look like e-mail addresses on various pages.
|
|
||||||
|
|
||||||
* "git apply --3way" has always been "to fall back to 3-way merge
|
|
||||||
only when straight application fails". Swap the order of falling
|
|
||||||
back so that 3-way is always attempted first (only when the option
|
|
||||||
is given, of course) and then straight patch application is used as
|
|
||||||
a fallback when it fails.
|
|
||||||
|
|
||||||
* "git apply" now takes "--3way" and "--cached" at the same time, and
|
|
||||||
work and record results only in the index.
|
|
||||||
|
|
||||||
* The command line completion (in contrib/) has learned that
|
|
||||||
CHERRY_PICK_HEAD is a possible pseudo-ref.
|
|
||||||
|
|
||||||
* Userdiff patterns for "Scheme" has been added.
|
|
||||||
|
|
||||||
* "git log" learned "--diff-merges=<style>" option, with an
|
|
||||||
associated configuration variable log.diffMerges.
|
|
||||||
|
|
||||||
* "git log --format=..." placeholders learned %ah/%ch placeholders to
|
|
||||||
request the --date=human output.
|
|
||||||
|
|
||||||
* Replace GIT_CONFIG_NOSYSTEM mechanism to decline from reading the
|
|
||||||
system-wide configuration file with GIT_CONFIG_SYSTEM that lets
|
|
||||||
users specify from which file to read the system-wide configuration
|
|
||||||
(setting it to an empty file would essentially be the same as
|
|
||||||
setting NOSYSTEM), and introduce GIT_CONFIG_GLOBAL to override the
|
|
||||||
per-user configuration in $HOME/.gitconfig.
|
|
||||||
|
|
||||||
* "git add" and "git rm" learned not to touch those paths that are
|
|
||||||
outside of sparse checkout.
|
|
||||||
|
|
||||||
* "git rev-list" learns the "--filter=object:type=<type>" option,
|
|
||||||
which can be used to exclude objects of the given kind from the
|
|
||||||
packfile generated by pack-objects.
|
|
||||||
|
|
||||||
* The command line completion (in contrib/) for "git stash" has been
|
|
||||||
updated.
|
|
||||||
|
|
||||||
* "git subtree" updates.
|
|
||||||
|
|
||||||
* It is now documented that "format-patch" skips merges.
|
|
||||||
|
|
||||||
* Options to "git pack-objects" that take numeric values like
|
|
||||||
--window and --depth should not accept negative values; the input
|
|
||||||
validation has been tightened.
|
|
||||||
|
|
||||||
* The way the command line specified by the trailer.<token>.command
|
|
||||||
configuration variable receives the end-user supplied value was
|
|
||||||
both error prone and misleading. An alternative to achieve the
|
|
||||||
same goal in a safer and more intuitive way has been added, as
|
|
||||||
the trailer.<token>.cmd configuration variable, to replace it.
|
|
||||||
|
|
||||||
* "git add -i --dry-run" does not dry-run, which was surprising. The
|
|
||||||
combination of options has taught to error out.
|
|
||||||
|
|
||||||
* "git push" learns to discover common ancestor with the receiving
|
|
||||||
end over protocol v2. This will hopefully make "git push" as
|
|
||||||
efficient as "git fetch" in avoiding objects from getting
|
|
||||||
transferred unnecessarily.
|
|
||||||
|
|
||||||
* "git mailinfo" (hence "git am") learned the "--quoted-cr" option to
|
|
||||||
control how lines ending with CRLF wrapped in base64 or qp are
|
|
||||||
handled.
|
|
||||||
|
|
||||||
|
|
||||||
Performance, Internal Implementation, Development Support etc.
|
|
||||||
|
|
||||||
* Rename detection rework continues.
|
|
||||||
|
|
||||||
* GIT_TEST_FAIL_PREREQS is a mechanism to skip test pieces with
|
|
||||||
prerequisites to catch broken tests that depend on the side effects
|
|
||||||
of optional pieces, but did not work at all when negative
|
|
||||||
prerequisites were involved.
|
|
||||||
(merge 27d578d904 jk/fail-prereq-testfix later to maint).
|
|
||||||
|
|
||||||
* "git diff-index" codepath has been taught to trust fsmonitor status
|
|
||||||
to reduce number of lstat() calls.
|
|
||||||
(merge 7e5aa13d2c nk/diff-index-fsmonitor later to maint).
|
|
||||||
|
|
||||||
* Reorganize Makefile to allow building git.o and other essential
|
|
||||||
objects without extra stuff needed only for testing.
|
|
||||||
|
|
||||||
* Preparatory API changes for parallel checkout.
|
|
||||||
|
|
||||||
* A simple IPC interface gets introduced to build services like
|
|
||||||
fsmonitor on top.
|
|
||||||
|
|
||||||
* Fsck API clean-up.
|
|
||||||
|
|
||||||
* SECURITY.md that is facing individual contributors and end users
|
|
||||||
has been introduced. Also a procedure to follow when preparing
|
|
||||||
embargoed releases has been spelled out.
|
|
||||||
(merge 09420b7648 js/security-md later to maint).
|
|
||||||
|
|
||||||
* Optimize "rev-list --use-bitmap-index --objects" corner case that
|
|
||||||
uses negative tags as the stopping points.
|
|
||||||
|
|
||||||
* CMake update for vsbuild.
|
|
||||||
|
|
||||||
* An on-disk reverse-index to map the in-pack location of an object
|
|
||||||
back to its object name across multiple packfiles is introduced.
|
|
||||||
|
|
||||||
* Generate [ec]tags under $(QUIET_GEN).
|
|
||||||
|
|
||||||
* Clean-up codepaths that implements "git send-email --validate"
|
|
||||||
option and improves the message from it.
|
|
||||||
|
|
||||||
* The last remnant of gettext-poison has been removed.
|
|
||||||
|
|
||||||
* The test framework has been taught to optionally turn the default
|
|
||||||
merge strategy to "ort" throughout the system where we use
|
|
||||||
three-way merges internally, like cherry-pick, rebase etc.,
|
|
||||||
primarily to enhance its test coverage (the strategy has been
|
|
||||||
available as an explicit "-s ort" choice).
|
|
||||||
|
|
||||||
* A bit of code clean-up and a lot of test clean-up around userdiff
|
|
||||||
area.
|
|
||||||
|
|
||||||
* Handling of "promisor packs" that allows certain objects to be
|
|
||||||
missing and lazily retrievable has been optimized (a bit).
|
|
||||||
|
|
||||||
* When packet_write() fails, we gave an extra error message
|
|
||||||
unnecessarily, which has been corrected.
|
|
||||||
|
|
||||||
* The checkout machinery has been taught to perform the actual
|
|
||||||
write-out of the files in parallel when able.
|
|
||||||
|
|
||||||
* Show errno in the trace output in the error codepath that calls
|
|
||||||
read_raw_ref method.
|
|
||||||
|
|
||||||
* Effort to make the command line completion (in contrib/) safe with
|
|
||||||
"set -u" continues.
|
|
||||||
|
|
||||||
* Tweak a few tests for "log --format=..." that show timestamps in
|
|
||||||
various formats.
|
|
||||||
|
|
||||||
* The reflog expiry machinery has been taught to emit trace events.
|
|
||||||
|
|
||||||
* Over-the-wire protocol learns a new request type to ask for object
|
|
||||||
sizes given a list of object names.
|
|
||||||
|
|
||||||
|
|
||||||
Fixes since v2.31
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
* The fsmonitor interface read from its input without making sure
|
|
||||||
there is something to read from. This bug is new in 2.31
|
|
||||||
timeframe.
|
|
||||||
|
|
||||||
* The data structure used by fsmonitor interface was not properly
|
|
||||||
duplicated during an in-core merge, leading to use-after-free etc.
|
|
||||||
|
|
||||||
* "git bisect" reimplemented more in C during 2.30 timeframe did not
|
|
||||||
take an annotated tag as a good/bad endpoint well. This regression
|
|
||||||
has been corrected.
|
|
||||||
|
|
||||||
* Fix macros that can silently inject unintended null-statements.
|
|
||||||
|
|
||||||
* CALLOC_ARRAY() macro replaces many uses of xcalloc().
|
|
||||||
|
|
||||||
* Update insn in Makefile comments to run fuzz-all target.
|
|
||||||
|
|
||||||
* Fix a corner case bug in "git mv" on case insensitive systems,
|
|
||||||
which was introduced in 2.29 timeframe.
|
|
||||||
|
|
||||||
* We had a code to diagnose and die cleanly when a required
|
|
||||||
clean/smudge filter is missing, but an assert before that
|
|
||||||
unnecessarily fired, hiding the end-user facing die() message.
|
|
||||||
(merge 6fab35f748 mt/cleanly-die-upon-missing-required-filter later to maint).
|
|
||||||
|
|
||||||
* Update C code that sets a few configuration variables when a remote
|
|
||||||
is configured so that it spells configuration variable names in the
|
|
||||||
canonical camelCase.
|
|
||||||
(merge 0f1da600e6 ab/remote-write-config-in-camel-case later to maint).
|
|
||||||
|
|
||||||
* A new configuration variable has been introduced to allow choosing
|
|
||||||
which version of the generation number gets used in the
|
|
||||||
commit-graph file.
|
|
||||||
(merge 702110aac6 ds/commit-graph-generation-config later to maint).
|
|
||||||
|
|
||||||
* Perf test update to work better in secondary worktrees.
|
|
||||||
(merge 36e834abc1 jk/perf-in-worktrees later to maint).
|
|
||||||
|
|
||||||
* Updates to memory allocation code around the use of pcre2 library.
|
|
||||||
(merge c1760352e0 ab/grep-pcre2-allocfix later to maint).
|
|
||||||
|
|
||||||
* "git -c core.bare=false clone --bare ..." would have segfaulted,
|
|
||||||
which has been corrected.
|
|
||||||
(merge 75555676ad bc/clone-bare-with-conflicting-config later to maint).
|
|
||||||
|
|
||||||
* When "git checkout" removes a path that does not exist in the
|
|
||||||
commit it is checking out, it wasn't careful enough not to follow
|
|
||||||
symbolic links, which has been corrected.
|
|
||||||
(merge fab78a0c3d mt/checkout-remove-nofollow later to maint).
|
|
||||||
|
|
||||||
* A few option description strings started with capital letters,
|
|
||||||
which were corrected.
|
|
||||||
(merge 5ee90326dc cc/downcase-opt-help later to maint).
|
|
||||||
|
|
||||||
* Plug or annotate remaining leaks that trigger while running the
|
|
||||||
very basic set of tests.
|
|
||||||
(merge 68ffe095a2 ah/plugleaks later to maint).
|
|
||||||
|
|
||||||
* The hashwrite() API uses a buffering mechanism to avoid calling
|
|
||||||
write(2) too frequently. This logic has been refactored to be
|
|
||||||
easier to understand.
|
|
||||||
(merge ddaf1f62e3 ds/clarify-hashwrite later to maint).
|
|
||||||
|
|
||||||
* "git cherry-pick/revert" with or without "--[no-]edit" did not spawn
|
|
||||||
the editor as expected (e.g. "revert --no-edit" after a conflict
|
|
||||||
still asked to edit the message), which has been corrected.
|
|
||||||
(merge 39edfd5cbc en/sequencer-edit-upon-conflict-fix later to maint).
|
|
||||||
|
|
||||||
* "git daemon" has been tightened against systems that take backslash
|
|
||||||
as directory separator.
|
|
||||||
(merge 9a7f1ce8b7 rs/daemon-sanitize-dir-sep later to maint).
|
|
||||||
|
|
||||||
* A NULL-dereference bug has been corrected in an error codepath in
|
|
||||||
"git for-each-ref", "git branch --list" etc.
|
|
||||||
(merge c685450880 jk/ref-filter-segfault-fix later to maint).
|
|
||||||
|
|
||||||
* Streamline the codepath to fix the UTF-8 encoding issues in the
|
|
||||||
argv[] and the prefix on macOS.
|
|
||||||
(merge c7d0e61016 tb/precompose-prefix-simplify later to maint).
|
|
||||||
|
|
||||||
* The command-line completion script (in contrib/) had a couple of
|
|
||||||
references that would have given a warning under the "-u" (nounset)
|
|
||||||
option.
|
|
||||||
(merge c5c0548d79 vs/completion-with-set-u later to maint).
|
|
||||||
|
|
||||||
* When "git pack-objects" makes a literal copy of a part of existing
|
|
||||||
packfile using the reachability bitmaps, its update to the progress
|
|
||||||
meter was broken.
|
|
||||||
(merge 8e118e8490 jk/pack-objects-bitmap-progress-fix later to maint).
|
|
||||||
|
|
||||||
* The dependencies for config-list.h and command-list.h were broken
|
|
||||||
when the former was split out of the latter, which has been
|
|
||||||
corrected.
|
|
||||||
(merge 56550ea718 sg/bugreport-fixes later to maint).
|
|
||||||
|
|
||||||
* "git push --quiet --set-upstream" was not quiet when setting the
|
|
||||||
upstream branch configuration, which has been corrected.
|
|
||||||
(merge f3cce896a8 ow/push-quiet-set-upstream later to maint).
|
|
||||||
|
|
||||||
* The prefetch task in "git maintenance" assumed that "git fetch"
|
|
||||||
from any remote would fetch all its local branches, which would
|
|
||||||
fetch too much if the user is interested in only a subset of
|
|
||||||
branches there.
|
|
||||||
(merge 32f67888d8 ds/maintenance-prefetch-fix later to maint).
|
|
||||||
|
|
||||||
* Clarify that pathnames recorded in Git trees are most often (but
|
|
||||||
not necessarily) encoded in UTF-8.
|
|
||||||
(merge 9364bf465d ab/pathname-encoding-doc later to maint).
|
|
||||||
|
|
||||||
* "git --config-env var=val cmd" weren't accepted (only
|
|
||||||
--config-env=var=val was).
|
|
||||||
(merge c331551ccf ps/config-env-option-with-separate-value later to maint).
|
|
||||||
|
|
||||||
* When the reachability bitmap is in effect, the "do not lose
|
|
||||||
recently created objects and those that are reachable from them"
|
|
||||||
safety to protect us from races were disabled by mistake, which has
|
|
||||||
been corrected.
|
|
||||||
(merge 2ba582ba4c jk/prune-with-bitmap-fix later to maint).
|
|
||||||
|
|
||||||
* Cygwin pathname handling fix.
|
|
||||||
(merge bccc37fdc7 ad/cygwin-no-backslashes-in-paths later to maint).
|
|
||||||
|
|
||||||
* "git rebase --[no-]reschedule-failed-exec" did not work well with
|
|
||||||
its configuration variable, which has been corrected.
|
|
||||||
(merge e5b32bffd1 ab/rebase-no-reschedule-failed-exec later to maint).
|
|
||||||
|
|
||||||
* Portability fix for command line completion script (in contrib/).
|
|
||||||
(merge f2acf763e2 si/zsh-complete-comment-fix later to maint).
|
|
||||||
|
|
||||||
* "git repack -A -d" in a partial clone unnecessarily loosened
|
|
||||||
objects in promisor pack.
|
|
||||||
|
|
||||||
* "git bisect skip" when custom words are used for new/old did not
|
|
||||||
work, which has been corrected.
|
|
||||||
|
|
||||||
* A few variants of informational message "Already up-to-date" has
|
|
||||||
been rephrased.
|
|
||||||
(merge ad9322da03 js/merge-already-up-to-date-message-reword later to maint).
|
|
||||||
|
|
||||||
* "git submodule update --quiet" did not propagate the quiet option
|
|
||||||
down to underlying "git fetch", which has been corrected.
|
|
||||||
(merge 62af4bdd42 nc/submodule-update-quiet later to maint).
|
|
||||||
|
|
||||||
* Document that our test can use "local" keyword.
|
|
||||||
(merge a84fd3bcc6 jc/test-allows-local later to maint).
|
|
||||||
|
|
||||||
* The word-diff mode has been taught to work better with a word
|
|
||||||
regexp that can match an empty string.
|
|
||||||
(merge 0324e8fc6b pw/word-diff-zero-width-matches later to maint).
|
|
||||||
|
|
||||||
* "git p4" learned to find branch points more efficiently.
|
|
||||||
(merge 6b79818bfb jk/p4-locate-branch-point-optim later to maint).
|
|
||||||
|
|
||||||
* When "git update-ref -d" removes a ref that is packed, it left
|
|
||||||
empty directories under $GIT_DIR/refs/ for
|
|
||||||
(merge 5f03e5126d wc/packed-ref-removal-cleanup later to maint).
|
|
||||||
|
|
||||||
* "git clean" and "git ls-files -i" had confusion around working on
|
|
||||||
or showing ignored paths inside an ignored directory, which has
|
|
||||||
been corrected.
|
|
||||||
(merge b548f0f156 en/dir-traversal later to maint).
|
|
||||||
|
|
||||||
* The handling of "%(push)" formatting element of "for-each-ref" and
|
|
||||||
friends was broken when the same codepath started handling
|
|
||||||
"%(push:<what>)", which has been corrected.
|
|
||||||
(merge 1e1c4c5eac zh/ref-filter-push-remote-fix later to maint).
|
|
||||||
|
|
||||||
* The bash prompt script (in contrib/) did not work under "set -u".
|
|
||||||
(merge 5c0cbdb107 en/prompt-under-set-u later to maint).
|
|
||||||
|
|
||||||
* The "chainlint" feature in the test framework is a handy way to
|
|
||||||
catch common mistakes in writing new tests, but tends to get
|
|
||||||
expensive. An knob to selectively disable it has been introduced
|
|
||||||
to help running tests that the developer has not modified.
|
|
||||||
(merge 2d86a96220 jk/test-chainlint-softer later to maint).
|
|
||||||
|
|
||||||
* The "rev-parse" command did not diagnose the lack of argument to
|
|
||||||
"--path-format" option, which was introduced in v2.31 era, which
|
|
||||||
has been corrected.
|
|
||||||
(merge 99fc555188 wm/rev-parse-path-format-wo-arg later to maint).
|
|
||||||
|
|
||||||
* Other code cleanup, docfix, build fix, etc.
|
|
||||||
(merge f451960708 dl/cat-file-doc-cleanup later to maint).
|
|
||||||
(merge 12604a8d0c sv/t9801-test-path-is-file-cleanup later to maint).
|
|
||||||
(merge ea7e63921c jr/doc-ignore-typofix later to maint).
|
|
||||||
(merge 23c781f173 ps/update-ref-trans-hook-doc later to maint).
|
|
||||||
(merge 42efa1231a jk/filter-branch-sha256 later to maint).
|
|
||||||
(merge 4c8e3dca6e tb/push-simple-uses-branch-merge-config later to maint).
|
|
||||||
(merge 6534d436a2 bs/asciidoctor-installation-hints later to maint).
|
|
||||||
(merge 47957485b3 ab/read-tree later to maint).
|
|
||||||
(merge 2be927f3d1 ab/diff-no-index-tests later to maint).
|
|
||||||
(merge 76593c09bb ab/detox-gettext-tests later to maint).
|
|
||||||
(merge 28e29ee38b jc/doc-format-patch-clarify later to maint).
|
|
||||||
(merge fc12b6fdde fm/user-manual-use-preface later to maint).
|
|
||||||
(merge dba94e3a85 cc/test-helper-bloom-usage-fix later to maint).
|
|
||||||
(merge 61a7660516 hn/reftable-tables-doc-update later to maint).
|
|
||||||
(merge 81ed96a9b2 jt/fetch-pack-request-fix later to maint).
|
|
||||||
(merge 151b6c2dd7 jc/doc-do-not-capitalize-clarification later to maint).
|
|
||||||
(merge 9160068ac6 js/access-nul-emulation-on-windows later to maint).
|
|
||||||
(merge 7a14acdbe6 po/diff-patch-doc later to maint).
|
|
||||||
(merge f91371b948 pw/patience-diff-clean-up later to maint).
|
|
||||||
(merge 3a7f0908b6 mt/clean-clean later to maint).
|
|
||||||
(merge d4e2d15a8b ab/streaming-simplify later to maint).
|
|
||||||
(merge 0e59f7ad67 ah/merge-ort-i18n later to maint).
|
|
||||||
(merge e6f68f62e0 ls/typofix later to maint).
|
|
@ -1,6 +0,0 @@
|
|||||||
Git v2.32.1 Release Notes
|
|
||||||
=========================
|
|
||||||
|
|
||||||
This release merges up the fixes that appear in v2.30.3 and
|
|
||||||
v2.31.2 to address the security issue CVE-2022-24765; see the
|
|
||||||
release notes for these versions for details.
|
|
@ -1,4 +0,0 @@
|
|||||||
Git Documentation/RelNotes/2.32.2.txt Release Notes
|
|
||||||
=========================
|
|
||||||
|
|
||||||
This release merges up the fixes that appear in v2.32.2.
|
|
@ -1,6 +0,0 @@
|
|||||||
Git v2.32.3 Release Notes
|
|
||||||
=========================
|
|
||||||
|
|
||||||
This release merges up the fixes that appear in v2.30.5 and
|
|
||||||
v2.31.4 to address the security issue CVE-2022-29187; see the
|
|
||||||
release notes for these versions for details.
|
|
@ -1,5 +0,0 @@
|
|||||||
Git v2.32.4 Release Notes
|
|
||||||
=========================
|
|
||||||
|
|
||||||
This release merges the security fix that appears in v2.30.6; see
|
|
||||||
the release notes for that version for details.
|
|
@ -117,13 +117,10 @@ If in doubt which identifier to use, run `git log --no-merges` on the
|
|||||||
files you are modifying to see the current conventions.
|
files you are modifying to see the current conventions.
|
||||||
|
|
||||||
[[summary-section]]
|
[[summary-section]]
|
||||||
The title sentence after the "area:" prefix omits the full stop at the
|
It's customary to start the remainder of the first line after "area: "
|
||||||
end, and its first word is not capitalized unless there is a reason to
|
with a lower-case letter. E.g. "doc: clarify...", not "doc:
|
||||||
capitalize it other than because it is the first word in the sentence.
|
Clarify...", or "githooks.txt: improve...", not "githooks.txt:
|
||||||
E.g. "doc: clarify...", not "doc: Clarify...", or "githooks.txt:
|
Improve...".
|
||||||
improve...", not "githooks.txt: Improve...". But "refs: HEAD is also
|
|
||||||
treated as a ref" is correct, as we spell `HEAD` in all caps even when
|
|
||||||
it appears in the middle of a sentence.
|
|
||||||
|
|
||||||
[[meaningful-message]]
|
[[meaningful-message]]
|
||||||
The body should provide a meaningful commit message, which:
|
The body should provide a meaningful commit message, which:
|
||||||
|
@ -119,8 +119,4 @@ advice.*::
|
|||||||
addEmptyPathspec::
|
addEmptyPathspec::
|
||||||
Advice shown if a user runs the add command without providing
|
Advice shown if a user runs the add command without providing
|
||||||
the pathspec parameter.
|
the pathspec parameter.
|
||||||
updateSparsePath::
|
|
||||||
Advice shown when either linkgit:git-add[1] or linkgit:git-rm[1]
|
|
||||||
is asked to update index entries outside the current sparse
|
|
||||||
checkout.
|
|
||||||
--
|
--
|
||||||
|
@ -21,24 +21,3 @@ checkout.guess::
|
|||||||
Provides the default value for the `--guess` or `--no-guess`
|
Provides the default value for the `--guess` or `--no-guess`
|
||||||
option in `git checkout` and `git switch`. See
|
option in `git checkout` and `git switch`. See
|
||||||
linkgit:git-switch[1] and linkgit:git-checkout[1].
|
linkgit:git-switch[1] and linkgit:git-checkout[1].
|
||||||
|
|
||||||
checkout.workers::
|
|
||||||
The number of parallel workers to use when updating the working tree.
|
|
||||||
The default is one, i.e. sequential execution. If set to a value less
|
|
||||||
than one, Git will use as many workers as the number of logical cores
|
|
||||||
available. This setting and `checkout.thresholdForParallelism` affect
|
|
||||||
all commands that perform checkout. E.g. checkout, clone, reset,
|
|
||||||
sparse-checkout, etc.
|
|
||||||
+
|
|
||||||
Note: parallel checkout usually delivers better performance for repositories
|
|
||||||
located on SSDs or over NFS. For repositories on spinning disks and/or machines
|
|
||||||
with a small number of cores, the default sequential checkout often performs
|
|
||||||
better. The size and compression level of a repository might also influence how
|
|
||||||
well the parallel version performs.
|
|
||||||
|
|
||||||
checkout.thresholdForParallelism::
|
|
||||||
When running parallel checkout with a small number of files, the cost
|
|
||||||
of subprocess spawning and inter-process communication might outweigh
|
|
||||||
the parallelization gains. This setting allows to define the minimum
|
|
||||||
number of files for which parallel checkout should be attempted. The
|
|
||||||
default is 100.
|
|
||||||
|
@ -2,7 +2,3 @@ clone.defaultRemoteName::
|
|||||||
The name of the remote to create when cloning a repository. Defaults to
|
The name of the remote to create when cloning a repository. Defaults to
|
||||||
`origin`, and can be overridden by passing the `--origin` command-line
|
`origin`, and can be overridden by passing the `--origin` command-line
|
||||||
option to linkgit:git-clone[1].
|
option to linkgit:git-clone[1].
|
||||||
|
|
||||||
clone.rejectShallow::
|
|
||||||
Reject to clone a repository if it is a shallow one, can be overridden by
|
|
||||||
passing option `--reject-shallow` in command line. See linkgit:git-clone[1]
|
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
commitGraph.generationVersion::
|
|
||||||
Specifies the type of generation number version to use when writing
|
|
||||||
or reading the commit-graph file. If version 1 is specified, then
|
|
||||||
the corrected commit dates will not be written or read. Defaults to
|
|
||||||
2.
|
|
||||||
|
|
||||||
commitGraph.maxNewFilters::
|
commitGraph.maxNewFilters::
|
||||||
Specifies the default value for the `--max-new-filters` option of `git
|
Specifies the default value for the `--max-new-filters` option of `git
|
||||||
commit-graph write` (c.f., linkgit:git-commit-graph[1]).
|
commit-graph write` (c.f., linkgit:git-commit-graph[1]).
|
||||||
|
@ -14,11 +14,6 @@ index.recordOffsetTable::
|
|||||||
Defaults to 'true' if index.threads has been explicitly enabled,
|
Defaults to 'true' if index.threads has been explicitly enabled,
|
||||||
'false' otherwise.
|
'false' otherwise.
|
||||||
|
|
||||||
index.sparse::
|
|
||||||
When enabled, write the index using sparse-directory entries. This
|
|
||||||
has no effect unless `core.sparseCheckout` and
|
|
||||||
`core.sparseCheckoutCone` are both enabled. Defaults to 'false'.
|
|
||||||
|
|
||||||
index.threads::
|
index.threads::
|
||||||
Specifies the number of threads to spawn when loading the index.
|
Specifies the number of threads to spawn when loading the index.
|
||||||
This is meant to reduce index load time on multiprocessor machines.
|
This is meant to reduce index load time on multiprocessor machines.
|
||||||
|
@ -24,11 +24,6 @@ log.excludeDecoration::
|
|||||||
the config option can be overridden by the `--decorate-refs`
|
the config option can be overridden by the `--decorate-refs`
|
||||||
option.
|
option.
|
||||||
|
|
||||||
log.diffMerges::
|
|
||||||
Set default diff format to be used for merge commits. See
|
|
||||||
`--diff-merges` in linkgit:git-log[1] for details.
|
|
||||||
Defaults to `separate`.
|
|
||||||
|
|
||||||
log.follow::
|
log.follow::
|
||||||
If `true`, `git log` will act as if the `--follow` option was used when
|
If `true`, `git log` will act as if the `--follow` option was used when
|
||||||
a single <path> is given. This has the same limitations as `--follow`,
|
a single <path> is given. This has the same limitations as `--follow`,
|
||||||
|
@ -122,21 +122,6 @@ pack.useSparse::
|
|||||||
commits contain certain types of direct renames. Default is
|
commits contain certain types of direct renames. Default is
|
||||||
`true`.
|
`true`.
|
||||||
|
|
||||||
pack.preferBitmapTips::
|
|
||||||
When selecting which commits will receive bitmaps, prefer a
|
|
||||||
commit at the tip of any reference that is a suffix of any value
|
|
||||||
of this configuration over any other commits in the "selection
|
|
||||||
window".
|
|
||||||
+
|
|
||||||
Note that setting this configuration to `refs/foo` does not mean that
|
|
||||||
the commits at the tips of `refs/foo/bar` and `refs/foo/baz` will
|
|
||||||
necessarily be selected. This is because commits are selected for
|
|
||||||
bitmaps from within a series of windows of variable length.
|
|
||||||
+
|
|
||||||
If a commit at the tip of any reference which is a suffix of any value
|
|
||||||
of this configuration is seen in a window, it is immediately given
|
|
||||||
preference over any other commit in that window.
|
|
||||||
|
|
||||||
pack.writeBitmaps (deprecated)::
|
pack.writeBitmaps (deprecated)::
|
||||||
This is a deprecated synonym for `repack.writeBitmaps`.
|
This is a deprecated synonym for `repack.writeBitmaps`.
|
||||||
|
|
||||||
|
@ -120,10 +120,3 @@ push.useForceIfIncludes::
|
|||||||
`--force-if-includes` as an option to linkgit:git-push[1]
|
`--force-if-includes` as an option to linkgit:git-push[1]
|
||||||
in the command line. Adding `--no-force-if-includes` at the
|
in the command line. Adding `--no-force-if-includes` at the
|
||||||
time of push overrides this configuration setting.
|
time of push overrides this configuration setting.
|
||||||
|
|
||||||
push.negotiate::
|
|
||||||
If set to "true", attempt to reduce the size of the packfile
|
|
||||||
sent by rounds of negotiation in which the client and the
|
|
||||||
server attempt to find commits in common. If "false", Git will
|
|
||||||
rely solely on the server's ref advertisement to find commits
|
|
||||||
in common.
|
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
rebase.useBuiltin::
|
||||||
|
Unused configuration variable. Used in Git versions 2.20 and
|
||||||
|
2.21 as an escape hatch to enable the legacy shellscript
|
||||||
|
implementation of rebase. Now the built-in rewrite of it in C
|
||||||
|
is always used. Setting this will emit a warning, to alert any
|
||||||
|
remaining users that setting this now does nothing.
|
||||||
|
|
||||||
rebase.backend::
|
rebase.backend::
|
||||||
Default backend to use for rebasing. Possible choices are
|
Default backend to use for rebasing. Possible choices are
|
||||||
'apply' or 'merge'. In the future, if the merge backend gains
|
'apply' or 'merge'. In the future, if the merge backend gains
|
||||||
|
@ -5,11 +5,6 @@ stash.useBuiltin::
|
|||||||
is always used. Setting this will emit a warning, to alert any
|
is always used. Setting this will emit a warning, to alert any
|
||||||
remaining users that setting this now does nothing.
|
remaining users that setting this now does nothing.
|
||||||
|
|
||||||
stash.showIncludeUntracked::
|
|
||||||
If this is set to true, the `git stash show` command will show
|
|
||||||
the untracked files of a stash entry. Defaults to false. See
|
|
||||||
description of 'show' command in linkgit:git-stash[1].
|
|
||||||
|
|
||||||
stash.showPatch::
|
stash.showPatch::
|
||||||
If this is set to true, the `git stash show` command without an
|
If this is set to true, the `git stash show` command without an
|
||||||
option will show the stash entry in patch form. Defaults to false.
|
option will show the stash entry in patch form. Defaults to false.
|
||||||
|
@ -59,16 +59,15 @@ uploadpack.allowFilter::
|
|||||||
|
|
||||||
uploadpackfilter.allow::
|
uploadpackfilter.allow::
|
||||||
Provides a default value for unspecified object filters (see: the
|
Provides a default value for unspecified object filters (see: the
|
||||||
below configuration variable). If set to `true`, this will also
|
below configuration variable).
|
||||||
enable all filters which get added in the future.
|
|
||||||
Defaults to `true`.
|
Defaults to `true`.
|
||||||
|
|
||||||
uploadpackfilter.<filter>.allow::
|
uploadpackfilter.<filter>.allow::
|
||||||
Explicitly allow or ban the object filter corresponding to
|
Explicitly allow or ban the object filter corresponding to
|
||||||
`<filter>`, where `<filter>` may be one of: `blob:none`,
|
`<filter>`, where `<filter>` may be one of: `blob:none`,
|
||||||
`blob:limit`, `object:type`, `tree`, `sparse:oid`, or `combine`.
|
`blob:limit`, `tree`, `sparse:oid`, or `combine`. If using
|
||||||
If using combined filters, both `combine` and all of the nested
|
combined filters, both `combine` and all of the nested filter
|
||||||
filter kinds must be allowed. Defaults to `uploadpackfilter.allow`.
|
kinds must be allowed. Defaults to `uploadpackfilter.allow`.
|
||||||
|
|
||||||
uploadpackfilter.tree.maxDepth::
|
uploadpackfilter.tree.maxDepth::
|
||||||
Only allow `--filter=tree:<n>` when `<n>` is no more than the value of
|
Only allow `--filter=tree:<n>` when `<n>` is no more than the value of
|
||||||
|
@ -11,7 +11,7 @@ linkgit:git-diff-files[1]
|
|||||||
with the `-p` option produces patch text.
|
with the `-p` option produces patch text.
|
||||||
You can customize the creation of patch text via the
|
You can customize the creation of patch text via the
|
||||||
`GIT_EXTERNAL_DIFF` and the `GIT_DIFF_OPTS` environment variables
|
`GIT_EXTERNAL_DIFF` and the `GIT_DIFF_OPTS` environment variables
|
||||||
(see linkgit:git[1]), and the `diff` attribute (see linkgit:gitattributes[5]).
|
(see linkgit:git[1]).
|
||||||
|
|
||||||
What the -p option produces is slightly different from the traditional
|
What the -p option produces is slightly different from the traditional
|
||||||
diff format:
|
diff format:
|
||||||
@ -74,11 +74,6 @@ separate lines indicate the old and the new mode.
|
|||||||
rename from b
|
rename from b
|
||||||
rename to a
|
rename to a
|
||||||
|
|
||||||
5. Hunk headers mention the name of the function to which the hunk
|
|
||||||
applies. See "Defining a custom hunk-header" in
|
|
||||||
linkgit:gitattributes[5] for details of how to tailor to this to
|
|
||||||
specific languages.
|
|
||||||
|
|
||||||
|
|
||||||
Combined diff format
|
Combined diff format
|
||||||
--------------------
|
--------------------
|
||||||
|
@ -34,7 +34,7 @@ endif::git-diff[]
|
|||||||
endif::git-format-patch[]
|
endif::git-format-patch[]
|
||||||
|
|
||||||
ifdef::git-log[]
|
ifdef::git-log[]
|
||||||
--diff-merges=(off|none|on|first-parent|1|separate|m|combined|c|dense-combined|cc)::
|
--diff-merges=(off|none|first-parent|1|separate|m|combined|c|dense-combined|cc)::
|
||||||
--no-diff-merges::
|
--no-diff-merges::
|
||||||
Specify diff format to be used for merge commits. Default is
|
Specify diff format to be used for merge commits. Default is
|
||||||
{diff-merges-default} unless `--first-parent` is in use, in which case
|
{diff-merges-default} unless `--first-parent` is in use, in which case
|
||||||
@ -45,24 +45,17 @@ ifdef::git-log[]
|
|||||||
Disable output of diffs for merge commits. Useful to override
|
Disable output of diffs for merge commits. Useful to override
|
||||||
implied value.
|
implied value.
|
||||||
+
|
+
|
||||||
--diff-merges=on:::
|
|
||||||
--diff-merges=m:::
|
|
||||||
-m:::
|
|
||||||
This option makes diff output for merge commits to be shown in
|
|
||||||
the default format. `-m` will produce the output only if `-p`
|
|
||||||
is given as well. The default format could be changed using
|
|
||||||
`log.diffMerges` configuration parameter, which default value
|
|
||||||
is `separate`.
|
|
||||||
+
|
|
||||||
--diff-merges=first-parent:::
|
--diff-merges=first-parent:::
|
||||||
--diff-merges=1:::
|
--diff-merges=1:::
|
||||||
This option makes merge commits show the full diff with
|
This option makes merge commits show the full diff with
|
||||||
respect to the first parent only.
|
respect to the first parent only.
|
||||||
+
|
+
|
||||||
--diff-merges=separate:::
|
--diff-merges=separate:::
|
||||||
|
--diff-merges=m:::
|
||||||
|
-m:::
|
||||||
This makes merge commits show the full diff with respect to
|
This makes merge commits show the full diff with respect to
|
||||||
each of the parents. Separate log entry and diff is generated
|
each of the parents. Separate log entry and diff is generated
|
||||||
for each parent.
|
for each parent. `-m` doesn't produce any output without `-p`.
|
||||||
+
|
+
|
||||||
--diff-merges=combined:::
|
--diff-merges=combined:::
|
||||||
--diff-merges=c:::
|
--diff-merges=c:::
|
||||||
@ -300,14 +293,11 @@ explained for the configuration variable `core.quotePath` (see
|
|||||||
linkgit:git-config[1]).
|
linkgit:git-config[1]).
|
||||||
|
|
||||||
--name-only::
|
--name-only::
|
||||||
Show only names of changed files. The file names are often encoded in UTF-8.
|
Show only names of changed files.
|
||||||
For more information see the discussion about encoding in the linkgit:git-log[1]
|
|
||||||
manual page.
|
|
||||||
|
|
||||||
--name-status::
|
--name-status::
|
||||||
Show only names and status of changed files. See the description
|
Show only names and status of changed files. See the description
|
||||||
of the `--diff-filter` option on what the status letters mean.
|
of the `--diff-filter` option on what the status letters mean.
|
||||||
Just like `--name-only` the file names are often encoded in UTF-8.
|
|
||||||
|
|
||||||
--submodule[=<format>]::
|
--submodule[=<format>]::
|
||||||
Specify how differences in submodules are shown. When specifying
|
Specify how differences in submodules are shown. When specifying
|
||||||
|
@ -110,11 +110,6 @@ ifndef::git-pull[]
|
|||||||
setting `fetch.writeCommitGraph`.
|
setting `fetch.writeCommitGraph`.
|
||||||
endif::git-pull[]
|
endif::git-pull[]
|
||||||
|
|
||||||
--prefetch::
|
|
||||||
Modify the configured refspec to place all refs into the
|
|
||||||
`refs/prefetch/` namespace. See the `prefetch` task in
|
|
||||||
linkgit:git-maintenance[1].
|
|
||||||
|
|
||||||
-p::
|
-p::
|
||||||
--prune::
|
--prune::
|
||||||
Before fetching, remove any remote-tracking references that no
|
Before fetching, remove any remote-tracking references that no
|
||||||
|
@ -15,7 +15,6 @@ SYNOPSIS
|
|||||||
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
|
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
|
||||||
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
|
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
|
||||||
[--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
|
[--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
|
||||||
[--quoted-cr=<action>]
|
|
||||||
[(<mbox> | <Maildir>)...]
|
[(<mbox> | <Maildir>)...]
|
||||||
'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=(diff|raw)])
|
'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=(diff|raw)])
|
||||||
|
|
||||||
@ -60,9 +59,6 @@ OPTIONS
|
|||||||
--no-scissors::
|
--no-scissors::
|
||||||
Ignore scissors lines (see linkgit:git-mailinfo[1]).
|
Ignore scissors lines (see linkgit:git-mailinfo[1]).
|
||||||
|
|
||||||
--quoted-cr=<action>::
|
|
||||||
This flag will be passed down to 'git mailinfo' (see linkgit:git-mailinfo[1]).
|
|
||||||
|
|
||||||
-m::
|
-m::
|
||||||
--message-id::
|
--message-id::
|
||||||
Pass the `-m` flag to 'git mailinfo' (see linkgit:git-mailinfo[1]),
|
Pass the `-m` flag to 'git mailinfo' (see linkgit:git-mailinfo[1]),
|
||||||
|
@ -84,13 +84,12 @@ OPTIONS
|
|||||||
|
|
||||||
-3::
|
-3::
|
||||||
--3way::
|
--3way::
|
||||||
Attempt 3-way merge if the patch records the identity of blobs it is supposed
|
When the patch does not apply cleanly, fall back on 3-way merge if
|
||||||
to apply to and we have those blobs available locally, possibly leaving the
|
the patch records the identity of blobs it is supposed to apply to,
|
||||||
|
and we have those blobs available locally, possibly leaving the
|
||||||
conflict markers in the files in the working tree for the user to
|
conflict markers in the files in the working tree for the user to
|
||||||
resolve. This option implies the `--index` option unless the
|
resolve. This option implies the `--index` option, and is incompatible
|
||||||
`--cached` option is used, and is incompatible with the `--reject` option.
|
with the `--reject` and the `--cached` options.
|
||||||
When used with the `--cached` option, any conflicts are left at higher stages
|
|
||||||
in the cache.
|
|
||||||
|
|
||||||
--build-fake-ancestor=<file>::
|
--build-fake-ancestor=<file>::
|
||||||
Newer 'git diff' output has embedded 'index information'
|
Newer 'git diff' output has embedded 'index information'
|
||||||
|
@ -35,42 +35,42 @@ OPTIONS
|
|||||||
|
|
||||||
-t::
|
-t::
|
||||||
Instead of the content, show the object type identified by
|
Instead of the content, show the object type identified by
|
||||||
`<object>`.
|
<object>.
|
||||||
|
|
||||||
-s::
|
-s::
|
||||||
Instead of the content, show the object size identified by
|
Instead of the content, show the object size identified by
|
||||||
`<object>`.
|
<object>.
|
||||||
|
|
||||||
-e::
|
-e::
|
||||||
Exit with zero status if `<object>` exists and is a valid
|
Exit with zero status if <object> exists and is a valid
|
||||||
object. If `<object>` is of an invalid format exit with non-zero and
|
object. If <object> is of an invalid format exit with non-zero and
|
||||||
emits an error on stderr.
|
emits an error on stderr.
|
||||||
|
|
||||||
-p::
|
-p::
|
||||||
Pretty-print the contents of `<object>` based on its type.
|
Pretty-print the contents of <object> based on its type.
|
||||||
|
|
||||||
<type>::
|
<type>::
|
||||||
Typically this matches the real type of `<object>` but asking
|
Typically this matches the real type of <object> but asking
|
||||||
for a type that can trivially be dereferenced from the given
|
for a type that can trivially be dereferenced from the given
|
||||||
`<object>` is also permitted. An example is to ask for a
|
<object> is also permitted. An example is to ask for a
|
||||||
"tree" with `<object>` being a commit object that contains it,
|
"tree" with <object> being a commit object that contains it,
|
||||||
or to ask for a "blob" with `<object>` being a tag object that
|
or to ask for a "blob" with <object> being a tag object that
|
||||||
points at it.
|
points at it.
|
||||||
|
|
||||||
--textconv::
|
--textconv::
|
||||||
Show the content as transformed by a textconv filter. In this case,
|
Show the content as transformed by a textconv filter. In this case,
|
||||||
`<object>` has to be of the form `<tree-ish>:<path>`, or `:<path>` in
|
<object> has to be of the form <tree-ish>:<path>, or :<path> in
|
||||||
order to apply the filter to the content recorded in the index at
|
order to apply the filter to the content recorded in the index at
|
||||||
`<path>`.
|
<path>.
|
||||||
|
|
||||||
--filters::
|
--filters::
|
||||||
Show the content as converted by the filters configured in
|
Show the content as converted by the filters configured in
|
||||||
the current working tree for the given `<path>` (i.e. smudge filters,
|
the current working tree for the given <path> (i.e. smudge filters,
|
||||||
end-of-line conversion, etc). In this case, `<object>` has to be of
|
end-of-line conversion, etc). In this case, <object> has to be of
|
||||||
the form `<tree-ish>:<path>`, or `:<path>`.
|
the form <tree-ish>:<path>, or :<path>.
|
||||||
|
|
||||||
--path=<path>::
|
--path=<path>::
|
||||||
For use with `--textconv` or `--filters`, to allow specifying an object
|
For use with --textconv or --filters, to allow specifying an object
|
||||||
name and a path separately, e.g. when it is difficult to figure out
|
name and a path separately, e.g. when it is difficult to figure out
|
||||||
the revision from which the blob came.
|
the revision from which the blob came.
|
||||||
|
|
||||||
@ -115,15 +115,15 @@ OPTIONS
|
|||||||
repository.
|
repository.
|
||||||
|
|
||||||
--allow-unknown-type::
|
--allow-unknown-type::
|
||||||
Allow `-s` or `-t` to query broken/corrupt objects of unknown type.
|
Allow -s or -t to query broken/corrupt objects of unknown type.
|
||||||
|
|
||||||
--follow-symlinks::
|
--follow-symlinks::
|
||||||
With `--batch` or `--batch-check`, follow symlinks inside the
|
With --batch or --batch-check, follow symlinks inside the
|
||||||
repository when requesting objects with extended SHA-1
|
repository when requesting objects with extended SHA-1
|
||||||
expressions of the form tree-ish:path-in-tree. Instead of
|
expressions of the form tree-ish:path-in-tree. Instead of
|
||||||
providing output about the link itself, provide output about
|
providing output about the link itself, provide output about
|
||||||
the linked-to object. If a symlink points outside the
|
the linked-to object. If a symlink points outside the
|
||||||
tree-ish (e.g. a link to `/foo` or a root-level link to `../foo`),
|
tree-ish (e.g. a link to /foo or a root-level link to ../foo),
|
||||||
the portion of the link which is outside the tree will be
|
the portion of the link which is outside the tree will be
|
||||||
printed.
|
printed.
|
||||||
+
|
+
|
||||||
@ -175,15 +175,15 @@ respectively print:
|
|||||||
|
|
||||||
OUTPUT
|
OUTPUT
|
||||||
------
|
------
|
||||||
If `-t` is specified, one of the `<type>`.
|
If `-t` is specified, one of the <type>.
|
||||||
|
|
||||||
If `-s` is specified, the size of the `<object>` in bytes.
|
If `-s` is specified, the size of the <object> in bytes.
|
||||||
|
|
||||||
If `-e` is specified, no output, unless the `<object>` is malformed.
|
If `-e` is specified, no output, unless the <object> is malformed.
|
||||||
|
|
||||||
If `-p` is specified, the contents of `<object>` are pretty-printed.
|
If `-p` is specified, the contents of <object> are pretty-printed.
|
||||||
|
|
||||||
If `<type>` is specified, the raw (though uncompressed) contents of the `<object>`
|
If <type> is specified, the raw (though uncompressed) contents of the <object>
|
||||||
will be returned.
|
will be returned.
|
||||||
|
|
||||||
BATCH OUTPUT
|
BATCH OUTPUT
|
||||||
@ -200,7 +200,7 @@ object, with placeholders of the form `%(atom)` expanded, followed by a
|
|||||||
newline. The available atoms are:
|
newline. The available atoms are:
|
||||||
|
|
||||||
`objectname`::
|
`objectname`::
|
||||||
The full hex representation of the object name.
|
The 40-hex object name of the object.
|
||||||
|
|
||||||
`objecttype`::
|
`objecttype`::
|
||||||
The type of the object (the same as `cat-file -t` reports).
|
The type of the object (the same as `cat-file -t` reports).
|
||||||
@ -215,9 +215,8 @@ newline. The available atoms are:
|
|||||||
|
|
||||||
`deltabase`::
|
`deltabase`::
|
||||||
If the object is stored as a delta on-disk, this expands to the
|
If the object is stored as a delta on-disk, this expands to the
|
||||||
full hex representation of the delta base object name.
|
40-hex sha1 of the delta base object. Otherwise, expands to the
|
||||||
Otherwise, expands to the null OID (all zeroes). See `CAVEATS`
|
null sha1 (40 zeroes). See `CAVEATS` below.
|
||||||
below.
|
|
||||||
|
|
||||||
`rest`::
|
`rest`::
|
||||||
If this atom is used in the output string, input lines are split
|
If this atom is used in the output string, input lines are split
|
||||||
@ -236,14 +235,14 @@ newline.
|
|||||||
For example, `--batch` without a custom format would produce:
|
For example, `--batch` without a custom format would produce:
|
||||||
|
|
||||||
------------
|
------------
|
||||||
<oid> SP <type> SP <size> LF
|
<sha1> SP <type> SP <size> LF
|
||||||
<contents> LF
|
<contents> LF
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Whereas `--batch-check='%(objectname) %(objecttype)'` would produce:
|
Whereas `--batch-check='%(objectname) %(objecttype)'` would produce:
|
||||||
|
|
||||||
------------
|
------------
|
||||||
<oid> SP <type> LF
|
<sha1> SP <type> LF
|
||||||
------------
|
------------
|
||||||
|
|
||||||
If a name is specified on stdin that cannot be resolved to an object in
|
If a name is specified on stdin that cannot be resolved to an object in
|
||||||
@ -259,7 +258,7 @@ If a name is specified that might refer to more than one object (an ambiguous sh
|
|||||||
<object> SP ambiguous LF
|
<object> SP ambiguous LF
|
||||||
------------
|
------------
|
||||||
|
|
||||||
If `--follow-symlinks` is used, and a symlink in the repository points
|
If --follow-symlinks is used, and a symlink in the repository points
|
||||||
outside the repository, then `cat-file` will ignore any custom format
|
outside the repository, then `cat-file` will ignore any custom format
|
||||||
and print:
|
and print:
|
||||||
|
|
||||||
@ -268,11 +267,11 @@ symlink SP <size> LF
|
|||||||
<symlink> LF
|
<symlink> LF
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The symlink will either be absolute (beginning with a `/`), or relative
|
The symlink will either be absolute (beginning with a /), or relative
|
||||||
to the tree root. For instance, if dir/link points to `../../foo`, then
|
to the tree root. For instance, if dir/link points to ../../foo, then
|
||||||
`<symlink>` will be `../foo`. `<size>` is the size of the symlink in bytes.
|
<symlink> will be ../foo. <size> is the size of the symlink in bytes.
|
||||||
|
|
||||||
If `--follow-symlinks` is used, the following error messages will be
|
If --follow-symlinks is used, the following error messages will be
|
||||||
displayed:
|
displayed:
|
||||||
|
|
||||||
------------
|
------------
|
||||||
|
@ -15,7 +15,7 @@ SYNOPSIS
|
|||||||
[--dissociate] [--separate-git-dir <git dir>]
|
[--dissociate] [--separate-git-dir <git dir>]
|
||||||
[--depth <depth>] [--[no-]single-branch] [--no-tags]
|
[--depth <depth>] [--[no-]single-branch] [--no-tags]
|
||||||
[--recurse-submodules[=<pathspec>]] [--[no-]shallow-submodules]
|
[--recurse-submodules[=<pathspec>]] [--[no-]shallow-submodules]
|
||||||
[--[no-]remote-submodules] [--jobs <n>] [--sparse] [--[no-]reject-shallow]
|
[--[no-]remote-submodules] [--jobs <n>] [--sparse]
|
||||||
[--filter=<filter>] [--] <repository>
|
[--filter=<filter>] [--] <repository>
|
||||||
[<directory>]
|
[<directory>]
|
||||||
|
|
||||||
@ -149,11 +149,6 @@ objects from the source repository into a pack in the cloned repository.
|
|||||||
--no-checkout::
|
--no-checkout::
|
||||||
No checkout of HEAD is performed after the clone is complete.
|
No checkout of HEAD is performed after the clone is complete.
|
||||||
|
|
||||||
--[no-]reject-shallow::
|
|
||||||
Fail if the source repository is a shallow repository.
|
|
||||||
The 'clone.rejectShallow' configuration variable can be used to
|
|
||||||
specify the default.
|
|
||||||
|
|
||||||
--bare::
|
--bare::
|
||||||
Make a 'bare' Git repository. That is, instead of
|
Make a 'bare' Git repository. That is, instead of
|
||||||
creating `<directory>` and placing the administrative
|
creating `<directory>` and placing the administrative
|
||||||
|
@ -9,13 +9,12 @@ SYNOPSIS
|
|||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git commit' [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]
|
'git commit' [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]
|
||||||
[--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|reword):]<commit>)]
|
[--dry-run] [(-c | -C | --fixup | --squash) <commit>]
|
||||||
[-F <file> | -m <msg>] [--reset-author] [--allow-empty]
|
[-F <file> | -m <msg>] [--reset-author] [--allow-empty]
|
||||||
[--allow-empty-message] [--no-verify] [-e] [--author=<author>]
|
[--allow-empty-message] [--no-verify] [-e] [--author=<author>]
|
||||||
[--date=<date>] [--cleanup=<mode>] [--[no-]status]
|
[--date=<date>] [--cleanup=<mode>] [--[no-]status]
|
||||||
[-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]
|
[-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]
|
||||||
[(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]
|
[-S[<keyid>]] [--] [<pathspec>...]
|
||||||
[--] [<pathspec>...]
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -87,44 +86,11 @@ OPTIONS
|
|||||||
Like '-C', but with `-c` the editor is invoked, so that
|
Like '-C', but with `-c` the editor is invoked, so that
|
||||||
the user can further edit the commit message.
|
the user can further edit the commit message.
|
||||||
|
|
||||||
--fixup=[(amend|reword):]<commit>::
|
--fixup=<commit>::
|
||||||
Create a new commit which "fixes up" `<commit>` when applied with
|
Construct a commit message for use with `rebase --autosquash`.
|
||||||
`git rebase --autosquash`. Plain `--fixup=<commit>` creates a
|
The commit message will be the subject line from the specified
|
||||||
"fixup!" commit which changes the content of `<commit>` but leaves
|
commit with a prefix of "fixup! ". See linkgit:git-rebase[1]
|
||||||
its log message untouched. `--fixup=amend:<commit>` is similar but
|
for details.
|
||||||
creates an "amend!" commit which also replaces the log message of
|
|
||||||
`<commit>` with the log message of the "amend!" commit.
|
|
||||||
`--fixup=reword:<commit>` creates an "amend!" commit which
|
|
||||||
replaces the log message of `<commit>` with its own log message
|
|
||||||
but makes no changes to the content of `<commit>`.
|
|
||||||
+
|
|
||||||
The commit created by plain `--fixup=<commit>` has a subject
|
|
||||||
composed of "fixup!" followed by the subject line from <commit>,
|
|
||||||
and is recognized specially by `git rebase --autosquash`. The `-m`
|
|
||||||
option may be used to supplement the log message of the created
|
|
||||||
commit, but the additional commentary will be thrown away once the
|
|
||||||
"fixup!" commit is squashed into `<commit>` by
|
|
||||||
`git rebase --autosquash`.
|
|
||||||
+
|
|
||||||
The commit created by `--fixup=amend:<commit>` is similar but its
|
|
||||||
subject is instead prefixed with "amend!". The log message of
|
|
||||||
<commit> is copied into the log message of the "amend!" commit and
|
|
||||||
opened in an editor so it can be refined. When `git rebase
|
|
||||||
--autosquash` squashes the "amend!" commit into `<commit>`, the
|
|
||||||
log message of `<commit>` is replaced by the refined log message
|
|
||||||
from the "amend!" commit. It is an error for the "amend!" commit's
|
|
||||||
log message to be empty unless `--allow-empty-message` is
|
|
||||||
specified.
|
|
||||||
+
|
|
||||||
`--fixup=reword:<commit>` is shorthand for `--fixup=amend:<commit>
|
|
||||||
--only`. It creates an "amend!" commit with only a log message
|
|
||||||
(ignoring any changes staged in the index). When squashed by `git
|
|
||||||
rebase --autosquash`, it replaces the log message of `<commit>`
|
|
||||||
without making any other changes.
|
|
||||||
+
|
|
||||||
Neither "fixup!" nor "amend!" commits change authorship of
|
|
||||||
`<commit>` when applied by `git rebase --autosquash`.
|
|
||||||
See linkgit:git-rebase[1] for details.
|
|
||||||
|
|
||||||
--squash=<commit>::
|
--squash=<commit>::
|
||||||
Construct a commit message for use with `rebase --autosquash`.
|
Construct a commit message for use with `rebase --autosquash`.
|
||||||
@ -200,17 +166,6 @@ The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`.
|
|||||||
|
|
||||||
include::signoff-option.txt[]
|
include::signoff-option.txt[]
|
||||||
|
|
||||||
--trailer <token>[(=|:)<value>]::
|
|
||||||
Specify a (<token>, <value>) pair that should be applied as a
|
|
||||||
trailer. (e.g. `git commit --trailer "Signed-off-by:C O Mitter \
|
|
||||||
<committer@example.com>" --trailer "Helped-by:C O Mitter \
|
|
||||||
<committer@example.com>"` will add the "Signed-off-by" trailer
|
|
||||||
and the "Helped-by" trailer to the commit message.)
|
|
||||||
The `trailer.*` configuration variables
|
|
||||||
(linkgit:git-interpret-trailers[1]) can be used to define if
|
|
||||||
a duplicated trailer is omitted, where in the run of trailers
|
|
||||||
each trailer would appear, and other details.
|
|
||||||
|
|
||||||
-n::
|
-n::
|
||||||
--no-verify::
|
--no-verify::
|
||||||
This option bypasses the pre-commit and commit-msg hooks.
|
This option bypasses the pre-commit and commit-msg hooks.
|
||||||
|
@ -340,11 +340,6 @@ GIT_CONFIG::
|
|||||||
Using the "--global" option forces this to ~/.gitconfig. Using the
|
Using the "--global" option forces this to ~/.gitconfig. Using the
|
||||||
"--system" option forces this to $(prefix)/etc/gitconfig.
|
"--system" option forces this to $(prefix)/etc/gitconfig.
|
||||||
|
|
||||||
GIT_CONFIG_GLOBAL::
|
|
||||||
GIT_CONFIG_SYSTEM::
|
|
||||||
Take the configuration from the given files instead from global or
|
|
||||||
system-level configuration. See linkgit:git[1] for details.
|
|
||||||
|
|
||||||
GIT_CONFIG_NOSYSTEM::
|
GIT_CONFIG_NOSYSTEM::
|
||||||
Whether to skip reading settings from the system-wide
|
Whether to skip reading settings from the system-wide
|
||||||
$(prefix)/etc/gitconfig file. See linkgit:git[1] for details.
|
$(prefix)/etc/gitconfig file. See linkgit:git[1] for details.
|
||||||
|
@ -159,7 +159,3 @@ empty string.
|
|||||||
+
|
+
|
||||||
Components which are missing from the URL (e.g., there is no
|
Components which are missing from the URL (e.g., there is no
|
||||||
username in the example above) will be left unset.
|
username in the example above) will be left unset.
|
||||||
|
|
||||||
GIT
|
|
||||||
---
|
|
||||||
Part of the linkgit:git[1] suite
|
|
||||||
|
@ -24,18 +24,6 @@ Usage:
|
|||||||
[verse]
|
[verse]
|
||||||
'git-cvsserver' [<options>] [pserver|server] [<directory> ...]
|
'git-cvsserver' [<options>] [pserver|server] [<directory> ...]
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
-----------
|
|
||||||
|
|
||||||
This application is a CVS emulation layer for Git.
|
|
||||||
|
|
||||||
It is highly functional. However, not all methods are implemented,
|
|
||||||
and for those methods that are implemented,
|
|
||||||
not all switches are implemented.
|
|
||||||
|
|
||||||
Testing has been done using both the CLI CVS client, and the Eclipse CVS
|
|
||||||
plugin. Most functionality works fine with both of these clients.
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
|
|
||||||
@ -69,6 +57,18 @@ access still needs to be enabled by the `gitcvs.enabled` config option
|
|||||||
unless `--export-all` was given, too.
|
unless `--export-all` was given, too.
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
|
||||||
|
This application is a CVS emulation layer for Git.
|
||||||
|
|
||||||
|
It is highly functional. However, not all methods are implemented,
|
||||||
|
and for those methods that are implemented,
|
||||||
|
not all switches are implemented.
|
||||||
|
|
||||||
|
Testing has been done using both the CLI CVS client, and the Eclipse CVS
|
||||||
|
plugin. Most functionality works fine with both of these clients.
|
||||||
|
|
||||||
LIMITATIONS
|
LIMITATIONS
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@ -36,28 +36,11 @@ SYNOPSIS
|
|||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
Prepare each non-merge commit with its "patch" in
|
Prepare each commit with its patch in
|
||||||
one "message" per commit, formatted to resemble a UNIX mailbox.
|
one file per commit, formatted to resemble UNIX mailbox format.
|
||||||
The output of this command is convenient for e-mail submission or
|
The output of this command is convenient for e-mail submission or
|
||||||
for use with 'git am'.
|
for use with 'git am'.
|
||||||
|
|
||||||
A "message" generated by the command consists of three parts:
|
|
||||||
|
|
||||||
* A brief metadata header that begins with `From <commit>`
|
|
||||||
with a fixed `Mon Sep 17 00:00:00 2001` datestamp to help programs
|
|
||||||
like "file(1)" to recognize that the file is an output from this
|
|
||||||
command, fields that record the author identity, the author date,
|
|
||||||
and the title of the change (taken from the first paragraph of the
|
|
||||||
commit log message).
|
|
||||||
|
|
||||||
* The second and subsequent paragraphs of the commit log message.
|
|
||||||
|
|
||||||
* The "patch", which is the "diff -p --stat" output (see
|
|
||||||
linkgit:git-diff[1]) between the commit and its parent.
|
|
||||||
|
|
||||||
The log message and the patch is separated by a line with a
|
|
||||||
three-dash line.
|
|
||||||
|
|
||||||
There are two ways to specify which commits to operate on.
|
There are two ways to specify which commits to operate on.
|
||||||
|
|
||||||
1. A single commit, <since>, specifies that the commits leading
|
1. A single commit, <since>, specifies that the commits leading
|
||||||
@ -238,11 +221,6 @@ populated with placeholder text.
|
|||||||
`--subject-prefix` option) has ` v<n>` appended to it. E.g.
|
`--subject-prefix` option) has ` v<n>` appended to it. E.g.
|
||||||
`--reroll-count=4` may produce `v4-0001-add-makefile.patch`
|
`--reroll-count=4` may produce `v4-0001-add-makefile.patch`
|
||||||
file that has "Subject: [PATCH v4 1/20] Add makefile" in it.
|
file that has "Subject: [PATCH v4 1/20] Add makefile" in it.
|
||||||
`<n>` does not have to be an integer (e.g. "--reroll-count=4.4",
|
|
||||||
or "--reroll-count=4rev2" are allowed), but the downside of
|
|
||||||
using such a reroll-count is that the range-diff/interdiff
|
|
||||||
with the previous version does not state exactly which
|
|
||||||
version the new interation is compared against.
|
|
||||||
|
|
||||||
--to=<email>::
|
--to=<email>::
|
||||||
Add a `To:` header to the email headers. This is in addition
|
Add a `To:` header to the email headers. This is in addition
|
||||||
@ -740,14 +718,6 @@ use it only when you know the recipient uses Git to apply your patch.
|
|||||||
$ git format-patch -3
|
$ git format-patch -3
|
||||||
------------
|
------------
|
||||||
|
|
||||||
CAVEATS
|
|
||||||
-------
|
|
||||||
|
|
||||||
Note that `format-patch` will omit merge commits from the output, even
|
|
||||||
if they are part of the requested range. A simple "patch" does not
|
|
||||||
include enough information for the receiving end to reproduce the same
|
|
||||||
merge commit.
|
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
linkgit:git-am[1], linkgit:git-send-email[1]
|
linkgit:git-am[1], linkgit:git-send-email[1]
|
||||||
|
@ -38,6 +38,38 @@ are lists of one or more search expressions separated by newline
|
|||||||
characters. An empty string as search expression matches all lines.
|
characters. An empty string as search expression matches all lines.
|
||||||
|
|
||||||
|
|
||||||
|
CONFIGURATION
|
||||||
|
-------------
|
||||||
|
|
||||||
|
grep.lineNumber::
|
||||||
|
If set to true, enable `-n` option by default.
|
||||||
|
|
||||||
|
grep.column::
|
||||||
|
If set to true, enable the `--column` option by default.
|
||||||
|
|
||||||
|
grep.patternType::
|
||||||
|
Set the default matching behavior. Using a value of 'basic', 'extended',
|
||||||
|
'fixed', or 'perl' will enable the `--basic-regexp`, `--extended-regexp`,
|
||||||
|
`--fixed-strings`, or `--perl-regexp` option accordingly, while the
|
||||||
|
value 'default' will return to the default matching behavior.
|
||||||
|
|
||||||
|
grep.extendedRegexp::
|
||||||
|
If set to true, enable `--extended-regexp` option by default. This
|
||||||
|
option is ignored when the `grep.patternType` option is set to a value
|
||||||
|
other than 'default'.
|
||||||
|
|
||||||
|
grep.threads::
|
||||||
|
Number of grep worker threads to use. If unset (or set to 0), Git will
|
||||||
|
use as many threads as the number of logical cores available.
|
||||||
|
|
||||||
|
grep.fullName::
|
||||||
|
If set to true, enable `--full-name` option by default.
|
||||||
|
|
||||||
|
grep.fallbackToNoIndex::
|
||||||
|
If set to true, fall back to git grep --no-index if git grep
|
||||||
|
is executed outside of a git repository. Defaults to false.
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
--cached::
|
--cached::
|
||||||
@ -331,38 +363,6 @@ with multiple threads might perform slower than single threaded if `--textconv`
|
|||||||
is given and there're too many text conversions. So if you experience low
|
is given and there're too many text conversions. So if you experience low
|
||||||
performance in this case, it might be desirable to use `--threads=1`.
|
performance in this case, it might be desirable to use `--threads=1`.
|
||||||
|
|
||||||
CONFIGURATION
|
|
||||||
-------------
|
|
||||||
|
|
||||||
grep.lineNumber::
|
|
||||||
If set to true, enable `-n` option by default.
|
|
||||||
|
|
||||||
grep.column::
|
|
||||||
If set to true, enable the `--column` option by default.
|
|
||||||
|
|
||||||
grep.patternType::
|
|
||||||
Set the default matching behavior. Using a value of 'basic', 'extended',
|
|
||||||
'fixed', or 'perl' will enable the `--basic-regexp`, `--extended-regexp`,
|
|
||||||
`--fixed-strings`, or `--perl-regexp` option accordingly, while the
|
|
||||||
value 'default' will return to the default matching behavior.
|
|
||||||
|
|
||||||
grep.extendedRegexp::
|
|
||||||
If set to true, enable `--extended-regexp` option by default. This
|
|
||||||
option is ignored when the `grep.patternType` option is set to a value
|
|
||||||
other than 'default'.
|
|
||||||
|
|
||||||
grep.threads::
|
|
||||||
Number of grep worker threads to use. If unset (or set to 0), Git will
|
|
||||||
use as many threads as the number of logical cores available.
|
|
||||||
|
|
||||||
grep.fullName::
|
|
||||||
If set to true, enable `--full-name` option by default.
|
|
||||||
|
|
||||||
grep.fallbackToNoIndex::
|
|
||||||
If set to true, fall back to git grep --no-index if git grep
|
|
||||||
is executed outside of a git repository. Defaults to false.
|
|
||||||
|
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
---
|
---
|
||||||
Part of the linkgit:git[1] suite
|
Part of the linkgit:git[1] suite
|
||||||
|
@ -232,38 +232,25 @@ trailer.<token>.ifmissing::
|
|||||||
that option for trailers with the specified <token>.
|
that option for trailers with the specified <token>.
|
||||||
|
|
||||||
trailer.<token>.command::
|
trailer.<token>.command::
|
||||||
This option behaves in the same way as 'trailer.<token>.cmd', except
|
This option can be used to specify a shell command that will
|
||||||
that it doesn't pass anything as argument to the specified command.
|
be called to automatically add or modify a trailer with the
|
||||||
Instead the first occurrence of substring $ARG is replaced by the
|
specified <token>.
|
||||||
value that would be passed as argument.
|
|
||||||
+
|
+
|
||||||
The 'trailer.<token>.command' option has been deprecated in favor of
|
When this option is specified, the behavior is as if a special
|
||||||
'trailer.<token>.cmd' due to the fact that $ARG in the user's command is
|
'<token>=<value>' argument were added at the beginning of the command
|
||||||
only replaced once and that the original way of replacing $ARG is not safe.
|
line, where <value> is taken to be the standard output of the
|
||||||
|
specified command with any leading and trailing whitespace trimmed
|
||||||
|
off.
|
||||||
+
|
+
|
||||||
When both 'trailer.<token>.cmd' and 'trailer.<token>.command' are given
|
If the command contains the `$ARG` string, this string will be
|
||||||
for the same <token>, 'trailer.<token>.cmd' is used and
|
replaced with the <value> part of an existing trailer with the same
|
||||||
'trailer.<token>.command' is ignored.
|
<token>, if any, before the command is launched.
|
||||||
|
|
||||||
trailer.<token>.cmd::
|
|
||||||
This option can be used to specify a shell command that will be called:
|
|
||||||
once to automatically add a trailer with the specified <token>, and then
|
|
||||||
each time a '--trailer <token>=<value>' argument to modify the <value> of
|
|
||||||
the trailer that this option would produce.
|
|
||||||
+
|
+
|
||||||
When the specified command is first called to add a trailer
|
If some '<token>=<value>' arguments are also passed on the command
|
||||||
with the specified <token>, the behavior is as if a special
|
line, when a 'trailer.<token>.command' is configured, the command will
|
||||||
'--trailer <token>=<value>' argument was added at the beginning
|
also be executed for each of these arguments. And the <value> part of
|
||||||
of the "git interpret-trailers" command, where <value>
|
these arguments, if any, will be used to replace the `$ARG` string in
|
||||||
is taken to be the standard output of the command with any
|
the command.
|
||||||
leading and trailing whitespace trimmed off.
|
|
||||||
+
|
|
||||||
If some '--trailer <token>=<value>' arguments are also passed
|
|
||||||
on the command line, the command is called again once for each
|
|
||||||
of these arguments with the same <token>. And the <value> part
|
|
||||||
of these arguments, if any, will be passed to the command as its
|
|
||||||
first argument. This way the command can produce a <value> computed
|
|
||||||
from the <value> passed in the '--trailer <token>=<value>' argument.
|
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
@ -346,55 +333,6 @@ subject
|
|||||||
Fix #42
|
Fix #42
|
||||||
------------
|
------------
|
||||||
|
|
||||||
* Configure a 'help' trailer with a cmd use a script `glog-find-author`
|
|
||||||
which search specified author identity from git log in git repository
|
|
||||||
and show how it works:
|
|
||||||
+
|
|
||||||
------------
|
|
||||||
$ cat ~/bin/glog-find-author
|
|
||||||
#!/bin/sh
|
|
||||||
test -n "$1" && git log --author="$1" --pretty="%an <%ae>" -1 || true
|
|
||||||
$ git config trailer.help.key "Helped-by: "
|
|
||||||
$ git config trailer.help.ifExists "addIfDifferentNeighbor"
|
|
||||||
$ git config trailer.help.cmd "~/bin/glog-find-author"
|
|
||||||
$ git interpret-trailers --trailer="help:Junio" --trailer="help:Couder" <<EOF
|
|
||||||
> subject
|
|
||||||
>
|
|
||||||
> message
|
|
||||||
>
|
|
||||||
> EOF
|
|
||||||
subject
|
|
||||||
|
|
||||||
message
|
|
||||||
|
|
||||||
Helped-by: Junio C Hamano <gitster@pobox.com>
|
|
||||||
Helped-by: Christian Couder <christian.couder@gmail.com>
|
|
||||||
------------
|
|
||||||
|
|
||||||
* Configure a 'ref' trailer with a cmd use a script `glog-grep`
|
|
||||||
to grep last relevant commit from git log in the git repository
|
|
||||||
and show how it works:
|
|
||||||
+
|
|
||||||
------------
|
|
||||||
$ cat ~/bin/glog-grep
|
|
||||||
#!/bin/sh
|
|
||||||
test -n "$1" && git log --grep "$1" --pretty=reference -1 || true
|
|
||||||
$ git config trailer.ref.key "Reference-to: "
|
|
||||||
$ git config trailer.ref.ifExists "replace"
|
|
||||||
$ git config trailer.ref.cmd "~/bin/glog-grep"
|
|
||||||
$ git interpret-trailers --trailer="ref:Add copyright notices." <<EOF
|
|
||||||
> subject
|
|
||||||
>
|
|
||||||
> message
|
|
||||||
>
|
|
||||||
> EOF
|
|
||||||
subject
|
|
||||||
|
|
||||||
message
|
|
||||||
|
|
||||||
Reference-to: 8bc9a0c769 (Add copyright notices., 2005-04-07)
|
|
||||||
------------
|
|
||||||
|
|
||||||
* Configure a 'see' trailer with a command to show the subject of a
|
* Configure a 'see' trailer with a command to show the subject of a
|
||||||
commit that is related, and show how it works:
|
commit that is related, and show how it works:
|
||||||
+
|
+
|
||||||
|
@ -9,9 +9,7 @@ git-mailinfo - Extracts patch and authorship from a single e-mail message
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git mailinfo' [-k|-b] [-u | --encoding=<encoding> | -n]
|
'git mailinfo' [-k|-b] [-u | --encoding=<encoding> | -n] [--[no-]scissors] <msg> <patch>
|
||||||
[--[no-]scissors] [--quoted-cr=<action>]
|
|
||||||
<msg> <patch>
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -91,23 +89,6 @@ This can be enabled by default with the configuration option mailinfo.scissors.
|
|||||||
--no-scissors::
|
--no-scissors::
|
||||||
Ignore scissors lines. Useful for overriding mailinfo.scissors settings.
|
Ignore scissors lines. Useful for overriding mailinfo.scissors settings.
|
||||||
|
|
||||||
--quoted-cr=<action>::
|
|
||||||
Action when processes email messages sent with base64 or
|
|
||||||
quoted-printable encoding, and the decoded lines end with a CRLF
|
|
||||||
instead of a simple LF.
|
|
||||||
+
|
|
||||||
The valid actions are:
|
|
||||||
+
|
|
||||||
--
|
|
||||||
* `nowarn`: Git will do nothing when such a CRLF is found.
|
|
||||||
* `warn`: Git will issue a warning for each message if such a CRLF is
|
|
||||||
found.
|
|
||||||
* `strip`: Git will convert those CRLF to LF.
|
|
||||||
--
|
|
||||||
+
|
|
||||||
The default action could be set by configuration option `mailinfo.quotedCR`.
|
|
||||||
If no such configuration option has been set, `warn` will be used.
|
|
||||||
|
|
||||||
<msg>::
|
<msg>::
|
||||||
The commit log message extracted from e-mail, usually
|
The commit log message extracted from e-mail, usually
|
||||||
except the title line which comes from e-mail Subject.
|
except the title line which comes from e-mail Subject.
|
||||||
|
@ -92,8 +92,10 @@ commit-graph::
|
|||||||
prefetch::
|
prefetch::
|
||||||
The `prefetch` task updates the object directory with the latest
|
The `prefetch` task updates the object directory with the latest
|
||||||
objects from all registered remotes. For each remote, a `git fetch`
|
objects from all registered remotes. For each remote, a `git fetch`
|
||||||
command is run. The configured refspec is modified to place all
|
command is run. The refmap is custom to avoid updating local or remote
|
||||||
requested refs within `refs/prefetch/`. Also, tags are not updated.
|
branches (those in `refs/heads` or `refs/remotes`). Instead, the
|
||||||
|
remote refs are stored in `refs/prefetch/<remote>/`. Also, tags are
|
||||||
|
not updated.
|
||||||
+
|
+
|
||||||
This is done to avoid disrupting the remote-tracking branches. The end users
|
This is done to avoid disrupting the remote-tracking branches. The end users
|
||||||
expect these refs to stay unmoved unless they initiate a fetch. With prefetch
|
expect these refs to stay unmoved unless they initiate a fetch. With prefetch
|
||||||
|
@ -11,6 +11,14 @@ SYNOPSIS
|
|||||||
[verse]
|
[verse]
|
||||||
'git mktag'
|
'git mktag'
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-------
|
||||||
|
|
||||||
|
--strict::
|
||||||
|
By default mktag turns on the equivalent of
|
||||||
|
linkgit:git-fsck[1] `--strict` mode. Use `--no-strict` to
|
||||||
|
disable it.
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
@ -37,14 +45,6 @@ the appropriate `fsck.<msg-id>` varible:
|
|||||||
|
|
||||||
git -c fsck.extraHeaderEntry=ignore mktag <my-tag-with-headers
|
git -c fsck.extraHeaderEntry=ignore mktag <my-tag-with-headers
|
||||||
|
|
||||||
OPTIONS
|
|
||||||
-------
|
|
||||||
|
|
||||||
--strict::
|
|
||||||
By default mktag turns on the equivalent of
|
|
||||||
linkgit:git-fsck[1] `--strict` mode. Use `--no-strict` to
|
|
||||||
disable it.
|
|
||||||
|
|
||||||
Tag Format
|
Tag Format
|
||||||
----------
|
----------
|
||||||
A tag signature file, to be fed to this command's standard input,
|
A tag signature file, to be fed to this command's standard input,
|
||||||
|
@ -9,8 +9,7 @@ git-multi-pack-index - Write and verify multi-pack-indexes
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git multi-pack-index' [--object-dir=<dir>] [--[no-]progress]
|
'git multi-pack-index' [--object-dir=<dir>] [--[no-]progress] <subcommand>
|
||||||
[--preferred-pack=<pack>] <subcommand>
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -31,16 +30,7 @@ OPTIONS
|
|||||||
The following subcommands are available:
|
The following subcommands are available:
|
||||||
|
|
||||||
write::
|
write::
|
||||||
Write a new MIDX file. The following options are available for
|
Write a new MIDX file.
|
||||||
the `write` sub-command:
|
|
||||||
+
|
|
||||||
--
|
|
||||||
--preferred-pack=<pack>::
|
|
||||||
Optionally specify the tie-breaking pack used when
|
|
||||||
multiple packs contain the same object. If not given,
|
|
||||||
ties are broken in favor of the pack with the lowest
|
|
||||||
mtime.
|
|
||||||
--
|
|
||||||
|
|
||||||
verify::
|
verify::
|
||||||
Verify the contents of the MIDX file.
|
Verify the contents of the MIDX file.
|
||||||
|
@ -762,7 +762,3 @@ IMPLEMENTATION DETAILS
|
|||||||
message indicating the p4 depot location and change number. This
|
message indicating the p4 depot location and change number. This
|
||||||
line is used by later 'git p4 sync' operations to know which p4
|
line is used by later 'git p4 sync' operations to know which p4
|
||||||
changes are new.
|
changes are new.
|
||||||
|
|
||||||
GIT
|
|
||||||
---
|
|
||||||
Part of the linkgit:git[1] suite
|
|
||||||
|
@ -85,16 +85,6 @@ base-name::
|
|||||||
reference was included in the resulting packfile. This
|
reference was included in the resulting packfile. This
|
||||||
can be useful to send new tags to native Git clients.
|
can be useful to send new tags to native Git clients.
|
||||||
|
|
||||||
--stdin-packs::
|
|
||||||
Read the basenames of packfiles (e.g., `pack-1234abcd.pack`)
|
|
||||||
from the standard input, instead of object names or revision
|
|
||||||
arguments. The resulting pack contains all objects listed in the
|
|
||||||
included packs (those not beginning with `^`), excluding any
|
|
||||||
objects listed in the excluded packs (beginning with `^`).
|
|
||||||
+
|
|
||||||
Incompatible with `--revs`, or options that imply `--revs` (such as
|
|
||||||
`--all`), with the exception of `--unpacked`, which is compatible.
|
|
||||||
|
|
||||||
--window=<n>::
|
--window=<n>::
|
||||||
--depth=<n>::
|
--depth=<n>::
|
||||||
These two options affect how the objects contained in
|
These two options affect how the objects contained in
|
||||||
|
@ -600,7 +600,7 @@ EXAMPLES
|
|||||||
|
|
||||||
`git push origin`::
|
`git push origin`::
|
||||||
Without additional configuration, pushes the current branch to
|
Without additional configuration, pushes the current branch to
|
||||||
the configured upstream (`branch.<name>.merge` configuration
|
the configured upstream (`remote.origin.merge` configuration
|
||||||
variable) if it has the same name as the current branch, and
|
variable) if it has the same name as the current branch, and
|
||||||
errors out without pushing otherwise.
|
errors out without pushing otherwise.
|
||||||
+
|
+
|
||||||
|
@ -200,6 +200,12 @@ Alternatively, you can undo the 'git rebase' with
|
|||||||
|
|
||||||
git rebase --abort
|
git rebase --abort
|
||||||
|
|
||||||
|
CONFIGURATION
|
||||||
|
-------------
|
||||||
|
|
||||||
|
include::config/rebase.txt[]
|
||||||
|
include::config/sequencer.txt[]
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
--onto <newbase>::
|
--onto <newbase>::
|
||||||
@ -587,17 +593,16 @@ See also INCOMPATIBLE OPTIONS below.
|
|||||||
|
|
||||||
--autosquash::
|
--autosquash::
|
||||||
--no-autosquash::
|
--no-autosquash::
|
||||||
When the commit log message begins with "squash! ..." or "fixup! ..."
|
When the commit log message begins with "squash! ..." (or
|
||||||
or "amend! ...", and there is already a commit in the todo list that
|
"fixup! ..."), and there is already a commit in the todo list that
|
||||||
matches the same `...`, automatically modify the todo list of
|
matches the same `...`, automatically modify the todo list of rebase
|
||||||
`rebase -i`, so that the commit marked for squashing comes right after
|
-i so that the commit marked for squashing comes right after the
|
||||||
the commit to be modified, and change the action of the moved commit
|
commit to be modified, and change the action of the moved commit
|
||||||
from `pick` to `squash` or `fixup` or `fixup -C` respectively. A commit
|
from `pick` to `squash` (or `fixup`). A commit matches the `...` if
|
||||||
matches the `...` if the commit subject matches, or if the `...` refers
|
the commit subject matches, or if the `...` refers to the commit's
|
||||||
to the commit's hash. As a fall-back, partial matches of the commit
|
hash. As a fall-back, partial matches of the commit subject work,
|
||||||
subject work, too. The recommended way to create fixup/amend/squash
|
too. The recommended way to create fixup/squash commits is by using
|
||||||
commits is by using the `--fixup`, `--fixup=amend:` or `--fixup=reword:`
|
the `--fixup`/`--squash` options of linkgit:git-commit[1].
|
||||||
and `--squash` options respectively of linkgit:git-commit[1].
|
|
||||||
+
|
+
|
||||||
If the `--autosquash` option is enabled by default using the
|
If the `--autosquash` option is enabled by default using the
|
||||||
configuration variable `rebase.autoSquash`, this option can be
|
configuration variable `rebase.autoSquash`, this option can be
|
||||||
@ -617,14 +622,6 @@ See also INCOMPATIBLE OPTIONS below.
|
|||||||
--no-reschedule-failed-exec::
|
--no-reschedule-failed-exec::
|
||||||
Automatically reschedule `exec` commands that failed. This only makes
|
Automatically reschedule `exec` commands that failed. This only makes
|
||||||
sense in interactive mode (or when an `--exec` option was provided).
|
sense in interactive mode (or when an `--exec` option was provided).
|
||||||
+
|
|
||||||
Even though this option applies once a rebase is started, it's set for
|
|
||||||
the whole rebase at the start based on either the
|
|
||||||
`rebase.rescheduleFailedExec` configuration (see linkgit:git-config[1]
|
|
||||||
or "CONFIGURATION" below) or whether this option is
|
|
||||||
provided. Otherwise an explicit `--no-reschedule-failed-exec` at the
|
|
||||||
start would be overridden by the presence of
|
|
||||||
`rebase.rescheduleFailedExec=true` configuration.
|
|
||||||
|
|
||||||
INCOMPATIBLE OPTIONS
|
INCOMPATIBLE OPTIONS
|
||||||
--------------------
|
--------------------
|
||||||
@ -890,17 +887,9 @@ If you want to fold two or more commits into one, replace the command
|
|||||||
"pick" for the second and subsequent commits with "squash" or "fixup".
|
"pick" for the second and subsequent commits with "squash" or "fixup".
|
||||||
If the commits had different authors, the folded commit will be
|
If the commits had different authors, the folded commit will be
|
||||||
attributed to the author of the first commit. The suggested commit
|
attributed to the author of the first commit. The suggested commit
|
||||||
message for the folded commit is the concatenation of the first
|
message for the folded commit is the concatenation of the commit
|
||||||
commit's message with those identified by "squash" commands, omitting the
|
messages of the first commit and of those with the "squash" command,
|
||||||
messages of commits identified by "fixup" commands, unless "fixup -c"
|
but omits the commit messages of commits with the "fixup" command.
|
||||||
is used. In that case the suggested commit message is only the message
|
|
||||||
of the "fixup -c" commit, and an editor is opened allowing you to edit
|
|
||||||
the message. The contents (patch) of the "fixup -c" commit are still
|
|
||||||
incorporated into the folded commit. If there is more than one "fixup -c"
|
|
||||||
commit, the message from the final one is used. You can also use
|
|
||||||
"fixup -C" to get the same behavior as "fixup -c" except without opening
|
|
||||||
an editor.
|
|
||||||
|
|
||||||
|
|
||||||
'git rebase' will stop when "pick" has been replaced with "edit" or
|
'git rebase' will stop when "pick" has been replaced with "edit" or
|
||||||
when a command fails due to merge errors. When you are done editing
|
when a command fails due to merge errors. When you are done editing
|
||||||
@ -1268,12 +1257,6 @@ merge tlsv1.3
|
|||||||
merge cmake
|
merge cmake
|
||||||
------------
|
------------
|
||||||
|
|
||||||
CONFIGURATION
|
|
||||||
-------------
|
|
||||||
|
|
||||||
include::config/rebase.txt[]
|
|
||||||
include::config/sequencer.txt[]
|
|
||||||
|
|
||||||
BUGS
|
BUGS
|
||||||
----
|
----
|
||||||
The todo list presented by the deprecated `--preserve-merges --interactive`
|
The todo list presented by the deprecated `--preserve-merges --interactive`
|
||||||
|
@ -165,29 +165,6 @@ depth is 4095.
|
|||||||
Pass the `--delta-islands` option to `git-pack-objects`, see
|
Pass the `--delta-islands` option to `git-pack-objects`, see
|
||||||
linkgit:git-pack-objects[1].
|
linkgit:git-pack-objects[1].
|
||||||
|
|
||||||
-g=<factor>::
|
|
||||||
--geometric=<factor>::
|
|
||||||
Arrange resulting pack structure so that each successive pack
|
|
||||||
contains at least `<factor>` times the number of objects as the
|
|
||||||
next-largest pack.
|
|
||||||
+
|
|
||||||
`git repack` ensures this by determining a "cut" of packfiles that need
|
|
||||||
to be repacked into one in order to ensure a geometric progression. It
|
|
||||||
picks the smallest set of packfiles such that as many of the larger
|
|
||||||
packfiles (by count of objects contained in that pack) may be left
|
|
||||||
intact.
|
|
||||||
+
|
|
||||||
Unlike other repack modes, the set of objects to pack is determined
|
|
||||||
uniquely by the set of packs being "rolled-up"; in other words, the
|
|
||||||
packs determined to need to be combined in order to restore a geometric
|
|
||||||
progression.
|
|
||||||
+
|
|
||||||
When `--unpacked` is specified, loose objects are implicitly included in
|
|
||||||
this "roll-up", without respect to their reachability. This is subject
|
|
||||||
to change in the future. This option (implying a drastically different
|
|
||||||
repack mode) is not guaranteed to work with all other combinations of
|
|
||||||
option to `git repack`.
|
|
||||||
|
|
||||||
CONFIGURATION
|
CONFIGURATION
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
@ -23,9 +23,7 @@ branch, and no updates to their contents can be staged in the index,
|
|||||||
though that default behavior can be overridden with the `-f` option.
|
though that default behavior can be overridden with the `-f` option.
|
||||||
When `--cached` is given, the staged content has to
|
When `--cached` is given, the staged content has to
|
||||||
match either the tip of the branch or the file on disk,
|
match either the tip of the branch or the file on disk,
|
||||||
allowing the file to be removed from just the index. When
|
allowing the file to be removed from just the index.
|
||||||
sparse-checkouts are in use (see linkgit:git-sparse-checkout[1]),
|
|
||||||
`git rm` will only remove paths within the sparse-checkout patterns.
|
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
|
@ -45,20 +45,6 @@ To avoid interfering with other worktrees, it first enables the
|
|||||||
When `--cone` is provided, the `core.sparseCheckoutCone` setting is
|
When `--cone` is provided, the `core.sparseCheckoutCone` setting is
|
||||||
also set, allowing for better performance with a limited set of
|
also set, allowing for better performance with a limited set of
|
||||||
patterns (see 'CONE PATTERN SET' below).
|
patterns (see 'CONE PATTERN SET' below).
|
||||||
+
|
|
||||||
Use the `--[no-]sparse-index` option to toggle the use of the sparse
|
|
||||||
index format. This reduces the size of the index to be more closely
|
|
||||||
aligned with your sparse-checkout definition. This can have significant
|
|
||||||
performance advantages for commands such as `git status` or `git add`.
|
|
||||||
This feature is still experimental. Some commands might be slower with
|
|
||||||
a sparse index until they are properly integrated with the feature.
|
|
||||||
+
|
|
||||||
**WARNING:** Using a sparse index requires modifying the index in a way
|
|
||||||
that is not completely understood by external tools. If you have trouble
|
|
||||||
with this compatibility, then run `git sparse-checkout init --no-sparse-index`
|
|
||||||
to rewrite your index to not be sparse. Older versions of Git will not
|
|
||||||
understand the sparse directory entries index extension and may fail to
|
|
||||||
interact with your repository until it is disabled.
|
|
||||||
|
|
||||||
'set'::
|
'set'::
|
||||||
Write a set of patterns to the sparse-checkout file, as given as
|
Write a set of patterns to the sparse-checkout file, as given as
|
||||||
|
@ -9,7 +9,7 @@ SYNOPSIS
|
|||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git stash' list [<log-options>]
|
'git stash' list [<log-options>]
|
||||||
'git stash' show [-u|--include-untracked|--only-untracked] [<diff-options>] [<stash>]
|
'git stash' show [<diff-options>] [<stash>]
|
||||||
'git stash' drop [-q|--quiet] [<stash>]
|
'git stash' drop [-q|--quiet] [<stash>]
|
||||||
'git stash' ( pop | apply ) [--index] [-q|--quiet] [<stash>]
|
'git stash' ( pop | apply ) [--index] [-q|--quiet] [<stash>]
|
||||||
'git stash' branch <branchname> [<stash>]
|
'git stash' branch <branchname> [<stash>]
|
||||||
@ -83,7 +83,7 @@ stash@{1}: On master: 9cc0589... Add git-stash
|
|||||||
The command takes options applicable to the 'git log'
|
The command takes options applicable to the 'git log'
|
||||||
command to control what is shown and how. See linkgit:git-log[1].
|
command to control what is shown and how. See linkgit:git-log[1].
|
||||||
|
|
||||||
show [-u|--include-untracked|--only-untracked] [<diff-options>] [<stash>]::
|
show [<diff-options>] [<stash>]::
|
||||||
|
|
||||||
Show the changes recorded in the stash entry as a diff between the
|
Show the changes recorded in the stash entry as a diff between the
|
||||||
stashed contents and the commit back when the stash entry was first
|
stashed contents and the commit back when the stash entry was first
|
||||||
@ -91,10 +91,8 @@ show [-u|--include-untracked|--only-untracked] [<diff-options>] [<stash>]::
|
|||||||
By default, the command shows the diffstat, but it will accept any
|
By default, the command shows the diffstat, but it will accept any
|
||||||
format known to 'git diff' (e.g., `git stash show -p stash@{1}`
|
format known to 'git diff' (e.g., `git stash show -p stash@{1}`
|
||||||
to view the second most recent entry in patch form).
|
to view the second most recent entry in patch form).
|
||||||
If no `<diff-option>` is provided, the default behavior will be given
|
You can use stash.showStat and/or stash.showPatch config variables
|
||||||
by the `stash.showStat`, and `stash.showPatch` config variables. You
|
to change the default behavior.
|
||||||
can also use `stash.showIncludeUntracked` to set whether
|
|
||||||
`--include-untracked` is enabled by default.
|
|
||||||
|
|
||||||
pop [--index] [-q|--quiet] [<stash>]::
|
pop [--index] [-q|--quiet] [<stash>]::
|
||||||
|
|
||||||
@ -162,18 +160,10 @@ up with `git clean`.
|
|||||||
|
|
||||||
-u::
|
-u::
|
||||||
--include-untracked::
|
--include-untracked::
|
||||||
--no-include-untracked::
|
This option is only valid for `push` and `save` commands.
|
||||||
When used with the `push` and `save` commands,
|
|
||||||
all untracked files are also stashed and then cleaned up with
|
|
||||||
`git clean`.
|
|
||||||
+
|
+
|
||||||
When used with the `show` command, show the untracked files in the stash
|
All untracked files are also stashed and then cleaned up with
|
||||||
entry as part of the diff.
|
`git clean`.
|
||||||
|
|
||||||
--only-untracked::
|
|
||||||
This option is only valid for the `show` command.
|
|
||||||
+
|
|
||||||
Show only the untracked files in the stash entry as part of the diff.
|
|
||||||
|
|
||||||
--index::
|
--index::
|
||||||
This option is only valid for `pop` and `apply` commands.
|
This option is only valid for `pop` and `apply` commands.
|
||||||
|
@ -1061,6 +1061,25 @@ with different name spaces. For example:
|
|||||||
branches = stable/*:refs/remotes/svn/stable/*
|
branches = stable/*:refs/remotes/svn/stable/*
|
||||||
branches = debug/*:refs/remotes/svn/debug/*
|
branches = debug/*:refs/remotes/svn/debug/*
|
||||||
|
|
||||||
|
BUGS
|
||||||
|
----
|
||||||
|
|
||||||
|
We ignore all SVN properties except svn:executable. Any unhandled
|
||||||
|
properties are logged to $GIT_DIR/svn/<refname>/unhandled.log
|
||||||
|
|
||||||
|
Renamed and copied directories are not detected by Git and hence not
|
||||||
|
tracked when committing to SVN. I do not plan on adding support for
|
||||||
|
this as it's quite difficult and time-consuming to get working for all
|
||||||
|
the possible corner cases (Git doesn't do it, either). Committing
|
||||||
|
renamed and copied files is fully supported if they're similar enough
|
||||||
|
for Git to detect them.
|
||||||
|
|
||||||
|
In SVN, it is possible (though discouraged) to commit changes to a tag
|
||||||
|
(because a tag is just a directory copy, thus technically the same as a
|
||||||
|
branch). When cloning an SVN repository, 'git svn' cannot know if such a
|
||||||
|
commit to a tag will happen in the future. Thus it acts conservatively
|
||||||
|
and imports all SVN tags as branches, prefixing the tag name with 'tags/'.
|
||||||
|
|
||||||
CONFIGURATION
|
CONFIGURATION
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@ -1147,25 +1166,6 @@ $GIT_DIR/svn/\**/.rev_map.*::
|
|||||||
if it is missing or not up to date. 'git svn reset' automatically
|
if it is missing or not up to date. 'git svn reset' automatically
|
||||||
rewinds it.
|
rewinds it.
|
||||||
|
|
||||||
BUGS
|
|
||||||
----
|
|
||||||
|
|
||||||
We ignore all SVN properties except svn:executable. Any unhandled
|
|
||||||
properties are logged to $GIT_DIR/svn/<refname>/unhandled.log
|
|
||||||
|
|
||||||
Renamed and copied directories are not detected by Git and hence not
|
|
||||||
tracked when committing to SVN. I do not plan on adding support for
|
|
||||||
this as it's quite difficult and time-consuming to get working for all
|
|
||||||
the possible corner cases (Git doesn't do it, either). Committing
|
|
||||||
renamed and copied files is fully supported if they're similar enough
|
|
||||||
for Git to detect them.
|
|
||||||
|
|
||||||
In SVN, it is possible (though discouraged) to commit changes to a tag
|
|
||||||
(because a tag is just a directory copy, thus technically the same as a
|
|
||||||
branch). When cloning an SVN repository, 'git svn' cannot know if such a
|
|
||||||
commit to a tag will happen in the future. Thus it acts conservatively
|
|
||||||
and imports all SVN tags as branches, prefixing the tag name with 'tags/'.
|
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
linkgit:git-rebase[1]
|
linkgit:git-rebase[1]
|
||||||
|
@ -13,7 +13,7 @@ SYNOPSIS
|
|||||||
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
|
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
|
||||||
[-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]
|
[-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]
|
||||||
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
|
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
|
||||||
[--super-prefix=<path>] [--config-env=<name>=<envvar>]
|
[--super-prefix=<path>] [--config-env <name>=<envvar>]
|
||||||
<command> [<args>]
|
<command> [<args>]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -670,16 +670,6 @@ for further details.
|
|||||||
If this environment variable is set to `0`, git will not prompt
|
If this environment variable is set to `0`, git will not prompt
|
||||||
on the terminal (e.g., when asking for HTTP authentication).
|
on the terminal (e.g., when asking for HTTP authentication).
|
||||||
|
|
||||||
`GIT_CONFIG_GLOBAL`::
|
|
||||||
`GIT_CONFIG_SYSTEM`::
|
|
||||||
Take the configuration from the given files instead from global or
|
|
||||||
system-level configuration files. If `GIT_CONFIG_SYSTEM` is set, the
|
|
||||||
system config file defined at build time (usually `/etc/gitconfig`)
|
|
||||||
will not be read. Likewise, if `GIT_CONFIG_GLOBAL` is set, neither
|
|
||||||
`$HOME/.gitconfig` nor `$XDG_CONFIG_HOME/git/config` will be read. Can
|
|
||||||
be set to `/dev/null` to skip reading configuration files of the
|
|
||||||
respective level.
|
|
||||||
|
|
||||||
`GIT_CONFIG_NOSYSTEM`::
|
`GIT_CONFIG_NOSYSTEM`::
|
||||||
Whether to skip reading settings from the system-wide
|
Whether to skip reading settings from the system-wide
|
||||||
`$(prefix)/etc/gitconfig` file. This environment variable can
|
`$(prefix)/etc/gitconfig` file. This environment variable can
|
||||||
|
@ -845,8 +845,6 @@ patterns are available:
|
|||||||
|
|
||||||
- `rust` suitable for source code in the Rust language.
|
- `rust` suitable for source code in the Rust language.
|
||||||
|
|
||||||
- `scheme` suitable for source code in the Scheme language.
|
|
||||||
|
|
||||||
- `tex` suitable for source code for LaTeX documents.
|
- `tex` suitable for source code for LaTeX documents.
|
||||||
|
|
||||||
|
|
||||||
@ -1176,8 +1174,7 @@ tag then no replacement will be done. The placeholders are the same
|
|||||||
as those for the option `--pretty=format:` of linkgit:git-log[1],
|
as those for the option `--pretty=format:` of linkgit:git-log[1],
|
||||||
except that they need to be wrapped like this: `$Format:PLACEHOLDERS$`
|
except that they need to be wrapped like this: `$Format:PLACEHOLDERS$`
|
||||||
in the file. E.g. the string `$Format:%H$` will be replaced by the
|
in the file. E.g. the string `$Format:%H$` will be replaced by the
|
||||||
commit hash. However, only one `%(describe)` placeholder is expanded
|
commit hash.
|
||||||
per archive to avoid denial-of-service attacks.
|
|
||||||
|
|
||||||
|
|
||||||
Packing objects
|
Packing objects
|
||||||
@ -1247,12 +1244,6 @@ to:
|
|||||||
[attr]binary -diff -merge -text
|
[attr]binary -diff -merge -text
|
||||||
------------
|
------------
|
||||||
|
|
||||||
NOTES
|
|
||||||
-----
|
|
||||||
|
|
||||||
Git does not follow symbolic links when accessing a `.gitattributes`
|
|
||||||
file in the working tree. This keeps behavior consistent when the file
|
|
||||||
is accessed from the index or a tree versus from the filesystem.
|
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
@ -187,7 +187,7 @@ mark a file pair as a rename and stop considering other candidates for
|
|||||||
better matches. At most, one comparison is done per file in this
|
better matches. At most, one comparison is done per file in this
|
||||||
preliminary pass; so if there are several remaining ext.txt files
|
preliminary pass; so if there are several remaining ext.txt files
|
||||||
throughout the directory hierarchy after exact rename detection, this
|
throughout the directory hierarchy after exact rename detection, this
|
||||||
preliminary step may be skipped for those files.
|
preliminary step will be skipped for those files.
|
||||||
|
|
||||||
Note. When the "-C" option is used with `--find-copies-harder`
|
Note. When the "-C" option is used with `--find-copies-harder`
|
||||||
option, 'git diff-{asterisk}' commands feed unmodified filepairs to
|
option, 'git diff-{asterisk}' commands feed unmodified filepairs to
|
||||||
|
@ -138,7 +138,7 @@ given); `template` (if a `-t` option was given or the
|
|||||||
configuration option `commit.template` is set); `merge` (if the
|
configuration option `commit.template` is set); `merge` (if the
|
||||||
commit is a merge or a `.git/MERGE_MSG` file exists); `squash`
|
commit is a merge or a `.git/MERGE_MSG` file exists); `squash`
|
||||||
(if a `.git/SQUASH_MSG` file exists); or `commit`, followed by
|
(if a `.git/SQUASH_MSG` file exists); or `commit`, followed by
|
||||||
a commit object name (if a `-c`, `-C` or `--amend` option was given).
|
a commit SHA-1 (if a `-c`, `-C` or `--amend` option was given).
|
||||||
|
|
||||||
If the exit status is non-zero, `git commit` will abort.
|
If the exit status is non-zero, `git commit` will abort.
|
||||||
|
|
||||||
@ -231,19 +231,19 @@ named remote is not being used both values will be the same.
|
|||||||
Information about what is to be pushed is provided on the hook's standard
|
Information about what is to be pushed is provided on the hook's standard
|
||||||
input with lines of the form:
|
input with lines of the form:
|
||||||
|
|
||||||
<local ref> SP <local object name> SP <remote ref> SP <remote object name> LF
|
<local ref> SP <local sha1> SP <remote ref> SP <remote sha1> LF
|
||||||
|
|
||||||
For instance, if the command +git push origin master:foreign+ were run the
|
For instance, if the command +git push origin master:foreign+ were run the
|
||||||
hook would receive a line like the following:
|
hook would receive a line like the following:
|
||||||
|
|
||||||
refs/heads/master 67890 refs/heads/foreign 12345
|
refs/heads/master 67890 refs/heads/foreign 12345
|
||||||
|
|
||||||
although the full object name would be supplied. If the foreign ref does not
|
although the full, 40-character SHA-1s would be supplied. If the foreign ref
|
||||||
yet exist the `<remote object name>` will be the all-zeroes object name. If a
|
does not yet exist the `<remote SHA-1>` will be 40 `0`. If a ref is to be
|
||||||
ref is to be deleted, the `<local ref>` will be supplied as `(delete)` and the
|
deleted, the `<local ref>` will be supplied as `(delete)` and the `<local
|
||||||
`<local object name>` will be the all-zeroes object name. If the local commit
|
SHA-1>` will be 40 `0`. If the local commit was specified by something other
|
||||||
was specified by something other than a name which could be expanded (such as
|
than a name which could be expanded (such as `HEAD~`, or a SHA-1) it will be
|
||||||
`HEAD~`, or an object name) it will be supplied as it was originally given.
|
supplied as it was originally given.
|
||||||
|
|
||||||
If this hook exits with a non-zero status, `git push` will abort without
|
If this hook exits with a non-zero status, `git push` will abort without
|
||||||
pushing anything. Information about why the push is rejected may be sent
|
pushing anything. Information about why the push is rejected may be sent
|
||||||
@ -268,7 +268,7 @@ input a line of the format:
|
|||||||
where `<old-value>` is the old object name stored in the ref,
|
where `<old-value>` is the old object name stored in the ref,
|
||||||
`<new-value>` is the new object name to be stored in the ref and
|
`<new-value>` is the new object name to be stored in the ref and
|
||||||
`<ref-name>` is the full name of the ref.
|
`<ref-name>` is the full name of the ref.
|
||||||
When creating a new ref, `<old-value>` is the all-zeroes object name.
|
When creating a new ref, `<old-value>` is 40 `0`.
|
||||||
|
|
||||||
If the hook exits with non-zero status, none of the refs will be
|
If the hook exits with non-zero status, none of the refs will be
|
||||||
updated. If the hook exits with zero, updating of individual refs can
|
updated. If the hook exits with zero, updating of individual refs can
|
||||||
@ -473,8 +473,7 @@ reference-transaction
|
|||||||
|
|
||||||
This hook is invoked by any Git command that performs reference
|
This hook is invoked by any Git command that performs reference
|
||||||
updates. It executes whenever a reference transaction is prepared,
|
updates. It executes whenever a reference transaction is prepared,
|
||||||
committed or aborted and may thus get called multiple times. The hook
|
committed or aborted and may thus get called multiple times.
|
||||||
does not cover symbolic references (but that may change in the future).
|
|
||||||
|
|
||||||
The hook takes exactly one argument, which is the current state the
|
The hook takes exactly one argument, which is the current state the
|
||||||
given reference transaction is in:
|
given reference transaction is in:
|
||||||
@ -493,14 +492,6 @@ receives on standard input a line of the format:
|
|||||||
|
|
||||||
<old-value> SP <new-value> SP <ref-name> LF
|
<old-value> SP <new-value> SP <ref-name> LF
|
||||||
|
|
||||||
where `<old-value>` is the old object name passed into the reference
|
|
||||||
transaction, `<new-value>` is the new object name to be stored in the
|
|
||||||
ref and `<ref-name>` is the full name of the ref. When force updating
|
|
||||||
the reference regardless of its current value or when the reference is
|
|
||||||
to be created anew, `<old-value>` is the all-zeroes object name. To
|
|
||||||
distinguish these cases, you can inspect the current value of
|
|
||||||
`<ref-name>` via `git rev-parse`.
|
|
||||||
|
|
||||||
The exit status of the hook is ignored for any state except for the
|
The exit status of the hook is ignored for any state except for the
|
||||||
"prepared" state. In the "prepared" state, a non-zero exit status will
|
"prepared" state. In the "prepared" state, a non-zero exit status will
|
||||||
cause the transaction to be aborted. The hook will not be called with
|
cause the transaction to be aborted. The hook will not be called with
|
||||||
@ -559,7 +550,7 @@ command-dependent arguments may be passed in the future.
|
|||||||
The hook receives a list of the rewritten commits on stdin, in the
|
The hook receives a list of the rewritten commits on stdin, in the
|
||||||
format
|
format
|
||||||
|
|
||||||
<old-object-name> SP <new-object-name> [ SP <extra-info> ] LF
|
<old-sha1> SP <new-sha1> [ SP <extra-info> ] LF
|
||||||
|
|
||||||
The 'extra-info' is again command-dependent. If it is empty, the
|
The 'extra-info' is again command-dependent. If it is empty, the
|
||||||
preceding SP is also omitted. Currently, no commands pass any
|
preceding SP is also omitted. Currently, no commands pass any
|
||||||
@ -575,7 +566,7 @@ rebase::
|
|||||||
For the 'squash' and 'fixup' operation, all commits that were
|
For the 'squash' and 'fixup' operation, all commits that were
|
||||||
squashed are listed as being rewritten to the squashed commit.
|
squashed are listed as being rewritten to the squashed commit.
|
||||||
This means that there will be several lines sharing the same
|
This means that there will be several lines sharing the same
|
||||||
'new-object-name'.
|
'new-sha1'.
|
||||||
+
|
+
|
||||||
The commits are guaranteed to be listed in the order that they were
|
The commits are guaranteed to be listed in the order that they were
|
||||||
processed by rebase.
|
processed by rebase.
|
||||||
|
@ -149,15 +149,11 @@ not tracked by Git remain untracked.
|
|||||||
To stop tracking a file that is currently tracked, use
|
To stop tracking a file that is currently tracked, use
|
||||||
'git rm --cached'.
|
'git rm --cached'.
|
||||||
|
|
||||||
Git does not follow symbolic links when accessing a `.gitignore` file in
|
|
||||||
the working tree. This keeps behavior consistent when the file is
|
|
||||||
accessed from the index or a tree versus from the filesystem.
|
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|
||||||
- The pattern `hello.*` matches any file or folder
|
- The pattern `hello.*` matches any file or folder
|
||||||
whose name begins with `hello.`. If one wants to restrict
|
whose name begins with `hello`. If one wants to restrict
|
||||||
this only to the directory and not in its subdirectories,
|
this only to the directory and not in its subdirectories,
|
||||||
one can prepend the pattern with a slash, i.e. `/hello.*`;
|
one can prepend the pattern with a slash, i.e. `/hello.*`;
|
||||||
the pattern now matches `hello.txt`, `hello.c` but not
|
the pattern now matches `hello.txt`, `hello.c` but not
|
||||||
|
@ -55,13 +55,6 @@ this would also match the 'Commit Name <commit@email.xx>' above:
|
|||||||
Proper Name <proper@email.xx> CoMmIt NaMe <CoMmIt@EmAiL.xX>
|
Proper Name <proper@email.xx> CoMmIt NaMe <CoMmIt@EmAiL.xX>
|
||||||
--
|
--
|
||||||
|
|
||||||
NOTES
|
|
||||||
-----
|
|
||||||
|
|
||||||
Git does not follow symbolic links when accessing a `.mailmap` file in
|
|
||||||
the working tree. This keeps behavior consistent when the file is
|
|
||||||
accessed from the index or a tree versus from the filesystem.
|
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
@ -98,14 +98,6 @@ submodule.<name>.shallow::
|
|||||||
shallow clone (with a history depth of 1) unless the user explicitly
|
shallow clone (with a history depth of 1) unless the user explicitly
|
||||||
asks for a non-shallow clone.
|
asks for a non-shallow clone.
|
||||||
|
|
||||||
NOTES
|
|
||||||
-----
|
|
||||||
|
|
||||||
Git does not allow the `.gitmodules` file within a working tree to be a
|
|
||||||
symbolic link, and will refuse to check out such a tree entry. This
|
|
||||||
keeps behavior consistent when the file is accessed from the index or a
|
|
||||||
tree versus from the filesystem, and helps Git reliably enforce security
|
|
||||||
checks of the file contents.
|
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
@ -62,7 +62,3 @@ git clone ext::'git --namespace=foo %s /tmp/prefixed.git'
|
|||||||
----------
|
----------
|
||||||
|
|
||||||
include::transfer-data-leaks.txt[]
|
include::transfer-data-leaks.txt[]
|
||||||
|
|
||||||
GIT
|
|
||||||
---
|
|
||||||
Part of the linkgit:git[1] suite
|
|
||||||
|
@ -751,17 +751,6 @@ default font sizes or lineheights are changed (e.g. via adding extra
|
|||||||
CSS stylesheet in `@stylesheets`), it may be appropriate to change
|
CSS stylesheet in `@stylesheets`), it may be appropriate to change
|
||||||
these values.
|
these values.
|
||||||
|
|
||||||
email-privacy::
|
|
||||||
Redact e-mail addresses from the generated HTML, etc. content.
|
|
||||||
This obscures e-mail addresses retrieved from the author/committer
|
|
||||||
and comment sections of the Git log.
|
|
||||||
It is meant to hinder web crawlers that harvest and abuse addresses.
|
|
||||||
Such crawlers may not respect robots.txt.
|
|
||||||
Note that users and user tools also see the addresses as redacted.
|
|
||||||
If Gitweb is not the final step in a workflow then subsequent steps
|
|
||||||
may misbehave because of the redacted information they receive.
|
|
||||||
Disabled by default.
|
|
||||||
|
|
||||||
highlight::
|
highlight::
|
||||||
Server-side syntax highlight support in "blob" view. It requires
|
Server-side syntax highlight support in "blob" view. It requires
|
||||||
`$highlight_bin` program to be available (see the description of
|
`$highlight_bin` program to be available (see the description of
|
||||||
|
@ -1,131 +0,0 @@
|
|||||||
Content-type: text/asciidoc
|
|
||||||
Abstract: When a critical vulnerability is discovered and fixed, we follow this
|
|
||||||
script to coordinate a public release.
|
|
||||||
|
|
||||||
How we coordinate embargoed releases
|
|
||||||
====================================
|
|
||||||
|
|
||||||
To protect Git users from critical vulnerabilities, we do not just release
|
|
||||||
fixed versions like regular maintenance releases. Instead, we coordinate
|
|
||||||
releases with packagers, keeping the fixes under an embargo until the release
|
|
||||||
date. That way, users will have a chance to upgrade on that date, no matter
|
|
||||||
what Operating System or distribution they run.
|
|
||||||
|
|
||||||
Open a Security Advisory draft
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
The first step is to https://github.com/git/git/security/advisories/new[open an
|
|
||||||
advisory]. Technically, it is not necessary, but it is convenient and saves a
|
|
||||||
bit of hassle. This advisory can also be used to obtain the CVE number and it
|
|
||||||
will give us a private fork associated with it that can be used to collaborate
|
|
||||||
on a fix.
|
|
||||||
|
|
||||||
Release date of the embargoed version
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
If the vulnerability affects Windows users, we want to have our friends over at
|
|
||||||
Visual Studio on board. This means we need to target a "Patch Tuesday" (i.e. a
|
|
||||||
second Tuesday of the month), at the minimum three weeks from heads-up to
|
|
||||||
coordinated release.
|
|
||||||
|
|
||||||
If the vulnerability affects the server side, or can benefit from scans on the
|
|
||||||
server side (i.e. if `git fsck` can detect an attack), it is important to give
|
|
||||||
all involved Git repository hosting sites enough time to scan all of those
|
|
||||||
repositories.
|
|
||||||
|
|
||||||
Notifying the Linux distributions
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
At most two weeks before release date, we need to send a notification to
|
|
||||||
distros@vs.openwall.org, preferably less than 7 days before the release date.
|
|
||||||
This will reach most (all?) Linux distributions. See an example below, and the
|
|
||||||
guidelines for this mailing list at
|
|
||||||
https://oss-security.openwall.org/wiki/mailing-lists/distros#how-to-use-the-lists[here].
|
|
||||||
|
|
||||||
Once the version has been published, we send a note about that to oss-security.
|
|
||||||
As an example, see https://www.openwall.com/lists/oss-security/2019/12/13/1[the
|
|
||||||
v2.24.1 mail];
|
|
||||||
https://oss-security.openwall.org/wiki/mailing-lists/oss-security[Here] are
|
|
||||||
their guidelines.
|
|
||||||
|
|
||||||
The mail to oss-security should also describe the exploit, and give credit to
|
|
||||||
the reporter(s): security researchers still receive too little respect for the
|
|
||||||
invaluable service they provide, and public credit goes a long way to keep them
|
|
||||||
paid by their respective organizations.
|
|
||||||
|
|
||||||
Technically, describing any exploit can be delayed up to 7 days, but we usually
|
|
||||||
refrain from doing that, including it right away.
|
|
||||||
|
|
||||||
As a courtesy we typically attach a Git bundle (as `.tar.xz` because the list
|
|
||||||
will drop `.bundle` attachments) in the mail to distros@ so that the involved
|
|
||||||
parties can take care of integrating/backporting them. This bundle is typically
|
|
||||||
created using a command like this:
|
|
||||||
|
|
||||||
git bundle create cve-xxx.bundle ^origin/master vA.B.C vD.E.F
|
|
||||||
tar cJvf cve-xxx.bundle.tar.xz cve-xxx.bundle
|
|
||||||
|
|
||||||
Example mail to distros@vs.openwall.org
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
....
|
|
||||||
To: distros@vs.openwall.org
|
|
||||||
Cc: git-security@googlegroups.com, <other people involved in the report/fix>
|
|
||||||
Subject: [vs] Upcoming Git security fix release
|
|
||||||
|
|
||||||
Team,
|
|
||||||
|
|
||||||
The Git project will release new versions on <date> at 10am Pacific Time or
|
|
||||||
soon thereafter. I have attached a Git bundle (embedded in a `.tar.xz` to avoid
|
|
||||||
it being dropped) which you can fetch into a clone of
|
|
||||||
https://github.com/git/git via `git fetch --tags /path/to/cve-xxx.bundle`,
|
|
||||||
containing the tags for versions <versions>.
|
|
||||||
|
|
||||||
You can verify with `git tag -v <tag>` that the versions were signed by
|
|
||||||
the Git maintainer, using the same GPG key as e.g. v2.24.0.
|
|
||||||
|
|
||||||
Please use these tags to prepare `git` packages for your various
|
|
||||||
distributions, using the appropriate tagged versions. The added test cases
|
|
||||||
help verify the correctness.
|
|
||||||
|
|
||||||
The addressed issues are:
|
|
||||||
|
|
||||||
<list of CVEs with a short description, typically copy/pasted from Git's
|
|
||||||
release notes, usually demo exploit(s), too>
|
|
||||||
|
|
||||||
Credit for finding the vulnerability goes to <reporter>, credit for fixing
|
|
||||||
it goes to <developer>.
|
|
||||||
|
|
||||||
Thanks,
|
|
||||||
<name>
|
|
||||||
|
|
||||||
....
|
|
||||||
|
|
||||||
Example mail to oss-security@lists.openwall.com
|
|
||||||
-----------------------------------------------
|
|
||||||
|
|
||||||
....
|
|
||||||
To: oss-security@lists.openwall.com
|
|
||||||
Cc: git-security@googlegroups.com, <other people involved in the report/fix>
|
|
||||||
Subject: git: <copy from security advisory>
|
|
||||||
|
|
||||||
Team,
|
|
||||||
|
|
||||||
The Git project released new versions on <date>, addressing <CVE>.
|
|
||||||
|
|
||||||
All supported platforms are affected in one way or another, and all Git
|
|
||||||
versions all the way back to <version> are affected. The fixed versions are:
|
|
||||||
<versions>.
|
|
||||||
|
|
||||||
Link to the announcement: <link to lore.kernel.org/git>
|
|
||||||
|
|
||||||
We highly recommend to upgrade.
|
|
||||||
|
|
||||||
The addressed issues are:
|
|
||||||
* <list of CVEs and their explanations, along with demo exploits>
|
|
||||||
|
|
||||||
Credit for finding the vulnerability goes to <reporter>, credit for fixing
|
|
||||||
it goes to <developer>.
|
|
||||||
|
|
||||||
Thanks,
|
|
||||||
<name>
|
|
||||||
....
|
|
@ -1,67 +1,71 @@
|
|||||||
#!/usr/bin/perl
|
#!/usr/bin/perl
|
||||||
|
|
||||||
use strict;
|
use File::Find;
|
||||||
use warnings;
|
use Getopt::Long;
|
||||||
|
|
||||||
# Parse arguments, a simple state machine for input like:
|
my $basedir = ".";
|
||||||
#
|
GetOptions("basedir=s" => \$basedir)
|
||||||
# howto/*.txt config/*.txt --section=1 git.txt git-add.txt [...] --to-lint git-add.txt a-file.txt [...]
|
or die("Cannot parse command line arguments\n");
|
||||||
my %TXT;
|
|
||||||
my %SECTION;
|
|
||||||
my $section;
|
|
||||||
my $lint_these = 0;
|
|
||||||
for my $arg (@ARGV) {
|
|
||||||
if (my ($sec) = $arg =~ /^--section=(\d+)$/s) {
|
|
||||||
$section = $sec;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
my ($name) = $arg =~ /^(.*?)\.txt$/s;
|
my $found_errors = 0;
|
||||||
unless (defined $section) {
|
|
||||||
$TXT{$name} = $arg;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
$SECTION{$name} = $section;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $exit_code = 0;
|
|
||||||
sub report {
|
sub report {
|
||||||
my ($pos, $line, $target, $msg) = @_;
|
my ($where, $what, $error) = @_;
|
||||||
substr($line, $pos) = "' <-- HERE";
|
print "$where: $error: $what\n";
|
||||||
$line =~ s/^\s+//;
|
$found_errors = 1;
|
||||||
print "$ARGV:$.: error: $target: $msg, shown with 'HERE' below:\n";
|
|
||||||
print "$ARGV:$.:\t'$line\n";
|
|
||||||
$exit_code = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ARGV = sort values %TXT;
|
sub grab_section {
|
||||||
die "BUG: Nothing to process!" unless @ARGV;
|
my ($page) = @_;
|
||||||
while (<>) {
|
open my $fh, "<", "$basedir/$page.txt";
|
||||||
my $line = $_;
|
my $firstline = <$fh>;
|
||||||
while ($line =~ m/linkgit:((.*?)\[(\d)\])/g) {
|
chomp $firstline;
|
||||||
my $pos = pos $line;
|
close $fh;
|
||||||
my ($target, $page, $section) = ($1, $2, $3);
|
my ($section) = ($firstline =~ /.*\((\d)\)$/);
|
||||||
|
return $section;
|
||||||
|
}
|
||||||
|
|
||||||
# De-AsciiDoc
|
sub lint {
|
||||||
$page =~ s/{litdd}/--/g;
|
my ($file) = @_;
|
||||||
|
open my $fh, "<", $file
|
||||||
|
or return;
|
||||||
|
while (<$fh>) {
|
||||||
|
my $where = "$file:$.";
|
||||||
|
while (s/linkgit:((.*?)\[(\d)\])//) {
|
||||||
|
my ($target, $page, $section) = ($1, $2, $3);
|
||||||
|
|
||||||
if (!exists $TXT{$page}) {
|
# De-AsciiDoc
|
||||||
report($pos, $line, $target, "link outside of our own docs");
|
$page =~ s/{litdd}/--/g;
|
||||||
next;
|
|
||||||
}
|
if ($page !~ /^git/) {
|
||||||
if (!exists $SECTION{$page}) {
|
report($where, $target, "nongit link");
|
||||||
report($pos, $line, $target, "link outside of our sectioned docs");
|
next;
|
||||||
next;
|
}
|
||||||
}
|
if (! -f "$basedir/$page.txt") {
|
||||||
my $real_section = $SECTION{$page};
|
report($where, $target, "no such source");
|
||||||
if ($section != $SECTION{$page}) {
|
next;
|
||||||
report($pos, $line, $target, "wrong section (should be $real_section)");
|
}
|
||||||
next;
|
$real_section = grab_section($page);
|
||||||
|
if ($real_section != $section) {
|
||||||
|
report($where, $target,
|
||||||
|
"wrong section (should be $real_section)");
|
||||||
|
next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# this resets our $. for each file
|
close $fh;
|
||||||
close ARGV if eof;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exit $exit_code;
|
sub lint_it {
|
||||||
|
lint($File::Find::name) if -f && /\.txt$/;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!@ARGV) {
|
||||||
|
find({ wanted => \&lint_it, no_chdir => 1 }, $basedir);
|
||||||
|
} else {
|
||||||
|
for (@ARGV) {
|
||||||
|
lint($_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit $found_errors;
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/perl
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
|
|
||||||
my $exit_code = 0;
|
|
||||||
sub report {
|
|
||||||
my ($target, $msg) = @_;
|
|
||||||
print "error: $target: $msg\n";
|
|
||||||
$exit_code = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
local $/;
|
|
||||||
while (my $slurp = <>) {
|
|
||||||
report($ARGV, "has no 'Part of the linkgit:git[1] suite' end blurb")
|
|
||||||
unless $slurp =~ m[
|
|
||||||
^GIT\n
|
|
||||||
---\n
|
|
||||||
\QPart of the linkgit:git[1] suite\E \n
|
|
||||||
\z
|
|
||||||
]mx;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit $exit_code;
|
|
@ -1,105 +0,0 @@
|
|||||||
#!/usr/bin/perl
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
|
|
||||||
my %SECTIONS;
|
|
||||||
{
|
|
||||||
my $order = 0;
|
|
||||||
%SECTIONS = (
|
|
||||||
'NAME' => {
|
|
||||||
required => 1,
|
|
||||||
order => $order++,
|
|
||||||
},
|
|
||||||
'SYNOPSIS' => {
|
|
||||||
required => 1,
|
|
||||||
order => $order++,
|
|
||||||
},
|
|
||||||
'DESCRIPTION' => {
|
|
||||||
required => 1,
|
|
||||||
order => $order++,
|
|
||||||
},
|
|
||||||
'OPTIONS' => {
|
|
||||||
order => $order++,
|
|
||||||
required => 0,
|
|
||||||
},
|
|
||||||
'CONFIGURATION' => {
|
|
||||||
order => $order++,
|
|
||||||
},
|
|
||||||
'BUGS' => {
|
|
||||||
order => $order++,
|
|
||||||
},
|
|
||||||
'SEE ALSO' => {
|
|
||||||
order => $order++,
|
|
||||||
},
|
|
||||||
'GIT' => {
|
|
||||||
required => 1,
|
|
||||||
order => $order++,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
my $SECTION_RX = do {
|
|
||||||
my ($names) = join "|", keys %SECTIONS;
|
|
||||||
qr/^($names)$/s;
|
|
||||||
};
|
|
||||||
|
|
||||||
my $exit_code = 0;
|
|
||||||
sub report {
|
|
||||||
my ($msg) = @_;
|
|
||||||
print "$ARGV:$.: $msg\n";
|
|
||||||
$exit_code = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $last_was_section;
|
|
||||||
my @actual_order;
|
|
||||||
while (my $line = <>) {
|
|
||||||
chomp $line;
|
|
||||||
if ($line =~ $SECTION_RX) {
|
|
||||||
push @actual_order => $line;
|
|
||||||
$last_was_section = 1;
|
|
||||||
# Have no "last" section yet, processing NAME
|
|
||||||
next if @actual_order == 1;
|
|
||||||
|
|
||||||
my @expected_order = sort {
|
|
||||||
$SECTIONS{$a}->{order} <=> $SECTIONS{$b}->{order}
|
|
||||||
} @actual_order;
|
|
||||||
|
|
||||||
my $expected_last = $expected_order[-2];
|
|
||||||
my $actual_last = $actual_order[-2];
|
|
||||||
if ($actual_last ne $expected_last) {
|
|
||||||
report("section '$line' incorrectly ordered, comes after '$actual_last'");
|
|
||||||
}
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
if ($last_was_section) {
|
|
||||||
my $last_section = $actual_order[-1];
|
|
||||||
if (length $last_section ne length $line) {
|
|
||||||
report("dashes under '$last_section' should match its length!");
|
|
||||||
}
|
|
||||||
if ($line !~ /^-+$/) {
|
|
||||||
report("dashes under '$last_section' should be '-' dashes!");
|
|
||||||
}
|
|
||||||
$last_was_section = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eof) {
|
|
||||||
# We have both a hash and an array to consider, for
|
|
||||||
# convenience
|
|
||||||
my %actual_sections;
|
|
||||||
@actual_sections{@actual_order} = ();
|
|
||||||
|
|
||||||
for my $section (sort keys %SECTIONS) {
|
|
||||||
next if !$SECTIONS{$section}->{required} or exists $actual_sections{$section};
|
|
||||||
report("has no required '$section' section!");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Reset per-file state
|
|
||||||
{
|
|
||||||
@actual_order = ();
|
|
||||||
# this resets our $. for each file
|
|
||||||
close ARGV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exit $exit_code;
|
|
@ -190,8 +190,6 @@ The placeholders are:
|
|||||||
'%ai':: author date, ISO 8601-like format
|
'%ai':: author date, ISO 8601-like format
|
||||||
'%aI':: author date, strict ISO 8601 format
|
'%aI':: author date, strict ISO 8601 format
|
||||||
'%as':: author date, short format (`YYYY-MM-DD`)
|
'%as':: author date, short format (`YYYY-MM-DD`)
|
||||||
'%ah':: author date, human style (like the `--date=human` option of
|
|
||||||
linkgit:git-rev-list[1])
|
|
||||||
'%cn':: committer name
|
'%cn':: committer name
|
||||||
'%cN':: committer name (respecting .mailmap, see
|
'%cN':: committer name (respecting .mailmap, see
|
||||||
linkgit:git-shortlog[1] or linkgit:git-blame[1])
|
linkgit:git-shortlog[1] or linkgit:git-blame[1])
|
||||||
@ -208,23 +206,8 @@ The placeholders are:
|
|||||||
'%ci':: committer date, ISO 8601-like format
|
'%ci':: committer date, ISO 8601-like format
|
||||||
'%cI':: committer date, strict ISO 8601 format
|
'%cI':: committer date, strict ISO 8601 format
|
||||||
'%cs':: committer date, short format (`YYYY-MM-DD`)
|
'%cs':: committer date, short format (`YYYY-MM-DD`)
|
||||||
'%ch':: committer date, human style (like the `--date=human` option of
|
|
||||||
linkgit:git-rev-list[1])
|
|
||||||
'%d':: ref names, like the --decorate option of linkgit:git-log[1]
|
'%d':: ref names, like the --decorate option of linkgit:git-log[1]
|
||||||
'%D':: ref names without the " (", ")" wrapping.
|
'%D':: ref names without the " (", ")" wrapping.
|
||||||
'%(describe[:options])':: human-readable name, like
|
|
||||||
linkgit:git-describe[1]; empty string for
|
|
||||||
undescribable commits. The `describe` string
|
|
||||||
may be followed by a colon and zero or more
|
|
||||||
comma-separated options. Descriptions can be
|
|
||||||
inconsistent when tags are added or removed at
|
|
||||||
the same time.
|
|
||||||
+
|
|
||||||
** 'match=<pattern>': Only consider tags matching the given
|
|
||||||
`glob(7)` pattern, excluding the "refs/tags/" prefix.
|
|
||||||
** 'exclude=<pattern>': Do not consider tags matching the given
|
|
||||||
`glob(7)` pattern, excluding the "refs/tags/" prefix.
|
|
||||||
|
|
||||||
'%S':: ref name given on the command line by which the commit was reached
|
'%S':: ref name given on the command line by which the commit was reached
|
||||||
(like `git log --source`), only works with `git log`
|
(like `git log --source`), only works with `git log`
|
||||||
'%e':: encoding
|
'%e':: encoding
|
||||||
@ -271,7 +254,7 @@ endif::git-rev-list[]
|
|||||||
`trailers` string may be followed by a colon
|
`trailers` string may be followed by a colon
|
||||||
and zero or more comma-separated options.
|
and zero or more comma-separated options.
|
||||||
If any option is provided multiple times the
|
If any option is provided multiple times the
|
||||||
last occurrence wins.
|
last occurance wins.
|
||||||
+
|
+
|
||||||
The boolean options accept an optional value `[=<BOOL>]`. The values
|
The boolean options accept an optional value `[=<BOOL>]`. The values
|
||||||
`true`, `false`, `on`, `off` etc. are all accepted. See the "boolean"
|
`true`, `false`, `on`, `off` etc. are all accepted. See the "boolean"
|
||||||
|
@ -892,9 +892,6 @@ or units. n may be zero. The suffixes k, m, and g can be used to name
|
|||||||
units in KiB, MiB, or GiB. For example, 'blob:limit=1k' is the same
|
units in KiB, MiB, or GiB. For example, 'blob:limit=1k' is the same
|
||||||
as 'blob:limit=1024'.
|
as 'blob:limit=1024'.
|
||||||
+
|
+
|
||||||
The form '--filter=object:type=(tag|commit|tree|blob)' omits all objects
|
|
||||||
which are not of the requested type.
|
|
||||||
+
|
|
||||||
The form '--filter=sparse:oid=<blob-ish>' uses a sparse-checkout
|
The form '--filter=sparse:oid=<blob-ish>' uses a sparse-checkout
|
||||||
specification contained in the blob (or blob-expression) '<blob-ish>'
|
specification contained in the blob (or blob-expression) '<blob-ish>'
|
||||||
to omit blobs that would not be not required for a sparse checkout on
|
to omit blobs that would not be not required for a sparse checkout on
|
||||||
@ -933,11 +930,6 @@ equivalent.
|
|||||||
--no-filter::
|
--no-filter::
|
||||||
Turn off any previous `--filter=` argument.
|
Turn off any previous `--filter=` argument.
|
||||||
|
|
||||||
--filter-provided-objects::
|
|
||||||
Filter the list of explicitly provided objects, which would otherwise
|
|
||||||
always be printed even if they did not match any of the filters. Only
|
|
||||||
useful with `--filter=`.
|
|
||||||
|
|
||||||
--filter-print-omitted::
|
--filter-print-omitted::
|
||||||
Only useful with `--filter=`; prints a list of the objects omitted
|
Only useful with `--filter=`; prints a list of the objects omitted
|
||||||
by the filter. Object IDs are prefixed with a ``~'' character.
|
by the filter. Object IDs are prefixed with a ``~'' character.
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
Error reporting in git
|
Error reporting in git
|
||||||
======================
|
======================
|
||||||
|
|
||||||
`BUG`, `die`, `usage`, `error`, and `warning` report errors of
|
`die`, `usage`, `error`, and `warning` report errors of various
|
||||||
various kinds.
|
kinds.
|
||||||
|
|
||||||
- `BUG` is for failed internal assertions that should never happen,
|
|
||||||
i.e. a bug in git itself.
|
|
||||||
|
|
||||||
- `die` is for fatal application errors. It prints a message to
|
- `die` is for fatal application errors. It prints a message to
|
||||||
the user and exits with status 128.
|
the user and exits with status 128.
|
||||||
@ -23,9 +20,6 @@ various kinds.
|
|||||||
without running into too many problems. Like `error`, it
|
without running into too many problems. Like `error`, it
|
||||||
returns -1 after reporting the situation to the caller.
|
returns -1 after reporting the situation to the caller.
|
||||||
|
|
||||||
These reports will be logged via the trace2 facility. See the "error"
|
|
||||||
event in link:api-trace2.txt[trace2 API].
|
|
||||||
|
|
||||||
Customizable error handlers
|
Customizable error handlers
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
Simple-IPC API
|
|
||||||
==============
|
|
||||||
|
|
||||||
The Simple-IPC API is a collection of `ipc_` prefixed library routines
|
|
||||||
and a basic communication protocol that allow an IPC-client process to
|
|
||||||
send an application-specific IPC-request message to an IPC-server
|
|
||||||
process and receive an application-specific IPC-response message.
|
|
||||||
|
|
||||||
Communication occurs over a named pipe on Windows and a Unix domain
|
|
||||||
socket on other platforms. IPC-clients and IPC-servers rendezvous at
|
|
||||||
a previously agreed-to application-specific pathname (which is outside
|
|
||||||
the scope of this design) that is local to the computer system.
|
|
||||||
|
|
||||||
The IPC-server routines within the server application process create a
|
|
||||||
thread pool to listen for connections and receive request messages
|
|
||||||
from multiple concurrent IPC-clients. When received, these messages
|
|
||||||
are dispatched up to the server application callbacks for handling.
|
|
||||||
IPC-server routines then incrementally relay responses back to the
|
|
||||||
IPC-client.
|
|
||||||
|
|
||||||
The IPC-client routines within a client application process connect
|
|
||||||
to the IPC-server and send a request message and wait for a response.
|
|
||||||
When received, the response is returned back the caller.
|
|
||||||
|
|
||||||
For example, the `fsmonitor--daemon` feature will be built as a server
|
|
||||||
application on top of the IPC-server library routines. It will have
|
|
||||||
threads watching for file system events and a thread pool waiting for
|
|
||||||
client connections. Clients, such as `git status` will request a list
|
|
||||||
of file system events since a point in time and the server will
|
|
||||||
respond with a list of changed files and directories. The formats of
|
|
||||||
the request and response are application-specific; the IPC-client and
|
|
||||||
IPC-server routines treat them as opaque byte streams.
|
|
||||||
|
|
||||||
|
|
||||||
Comparison with sub-process model
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
The Simple-IPC mechanism differs from the existing `sub-process.c`
|
|
||||||
model (Documentation/technical/long-running-process-protocol.txt) and
|
|
||||||
used by applications like Git-LFS. In the LFS-style sub-process model
|
|
||||||
the helper is started by the foreground process, communication happens
|
|
||||||
via a pair of file descriptors bound to the stdin/stdout of the
|
|
||||||
sub-process, the sub-process only serves the current foreground
|
|
||||||
process, and the sub-process exits when the foreground process
|
|
||||||
terminates.
|
|
||||||
|
|
||||||
In the Simple-IPC model the server is a very long-running service. It
|
|
||||||
can service many clients at the same time and has a private socket or
|
|
||||||
named pipe connection to each active client. It might be started
|
|
||||||
(on-demand) by the current client process or it might have been
|
|
||||||
started by a previous client or by the OS at boot time. The server
|
|
||||||
process is not associated with a terminal and it persists after
|
|
||||||
clients terminate. Clients do not have access to the stdin/stdout of
|
|
||||||
the server process and therefore must communicate over sockets or
|
|
||||||
named pipes.
|
|
||||||
|
|
||||||
|
|
||||||
Server startup and shutdown
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
How an application server based upon IPC-server is started is also
|
|
||||||
outside the scope of the Simple-IPC design and is a property of the
|
|
||||||
application using it. For example, the server might be started or
|
|
||||||
restarted during routine maintenance operations, or it might be
|
|
||||||
started as a system service during the system boot-up sequence, or it
|
|
||||||
might be started on-demand by a foreground Git command when needed.
|
|
||||||
|
|
||||||
Similarly, server shutdown is a property of the application using
|
|
||||||
the simple-ipc routines. For example, the server might decide to
|
|
||||||
shutdown when idle or only upon explicit request.
|
|
||||||
|
|
||||||
|
|
||||||
Simple-IPC protocol
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
The Simple-IPC protocol consists of a single request message from the
|
|
||||||
client and an optional response message from the server. Both the
|
|
||||||
client and server messages are unlimited in length and are terminated
|
|
||||||
with a flush packet.
|
|
||||||
|
|
||||||
The pkt-line routines (Documentation/technical/protocol-common.txt)
|
|
||||||
are used to simplify buffer management during message generation,
|
|
||||||
transmission, and reception. A flush packet is used to mark the end
|
|
||||||
of the message. This allows the sender to incrementally generate and
|
|
||||||
transmit the message. It allows the receiver to incrementally receive
|
|
||||||
the message in chunks and to know when they have received the entire
|
|
||||||
message.
|
|
||||||
|
|
||||||
The actual byte format of the client request and server response
|
|
||||||
messages are application specific. The IPC layer transmits and
|
|
||||||
receives them as opaque byte buffers without any concern for the
|
|
||||||
content within. It is the job of the calling application layer to
|
|
||||||
understand the contents of the request and response messages.
|
|
||||||
|
|
||||||
|
|
||||||
Summary
|
|
||||||
-------
|
|
||||||
|
|
||||||
Conceptually, the Simple-IPC protocol is similar to an HTTP REST
|
|
||||||
request. Clients connect, make an application-specific and
|
|
||||||
stateless request, receive an application-specific
|
|
||||||
response, and disconnect. It is a one round trip facility for
|
|
||||||
querying the server. The Simple-IPC routines hide the socket,
|
|
||||||
named pipe, and thread pool details and allow the application
|
|
||||||
layer to focus on the application at hand.
|
|
@ -465,7 +465,7 @@ completed.)
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
`"error"`::
|
`"error"`::
|
||||||
This event is emitted when one of the `BUG()`, `error()`, `die()`,
|
This event is emitted when one of the `error()`, `die()`,
|
||||||
`warning()`, or `usage()` functions are called.
|
`warning()`, or `usage()` functions are called.
|
||||||
+
|
+
|
||||||
------------
|
------------
|
||||||
|
@ -44,13 +44,6 @@ Git index format
|
|||||||
localization, no special casing of directory separator '/'). Entries
|
localization, no special casing of directory separator '/'). Entries
|
||||||
with the same name are sorted by their stage field.
|
with the same name are sorted by their stage field.
|
||||||
|
|
||||||
An index entry typically represents a file. However, if sparse-checkout
|
|
||||||
is enabled in cone mode (`core.sparseCheckoutCone` is enabled) and the
|
|
||||||
`extensions.sparseIndex` extension is enabled, then the index may
|
|
||||||
contain entries for directories outside of the sparse-checkout definition.
|
|
||||||
These entries have mode `040000`, include the `SKIP_WORKTREE` bit, and
|
|
||||||
the path ends in a directory separator.
|
|
||||||
|
|
||||||
32-bit ctime seconds, the last time a file's metadata changed
|
32-bit ctime seconds, the last time a file's metadata changed
|
||||||
this is stat(2) data
|
this is stat(2) data
|
||||||
|
|
||||||
@ -392,15 +385,3 @@ The remaining data of each directory block is grouped by type:
|
|||||||
in this block of entries.
|
in this block of entries.
|
||||||
|
|
||||||
- 32-bit count of cache entries in this block
|
- 32-bit count of cache entries in this block
|
||||||
|
|
||||||
== Sparse Directory Entries
|
|
||||||
|
|
||||||
When using sparse-checkout in cone mode, some entire directories within
|
|
||||||
the index can be summarized by pointing to a tree object instead of the
|
|
||||||
entire expanded list of paths within that tree. An index containing such
|
|
||||||
entries is a "sparse index". Index format versions 4 and less were not
|
|
||||||
implemented with such entries in mind. Thus, for these versions, an
|
|
||||||
index containing sparse directory entries will include this extension
|
|
||||||
with signature { 's', 'd', 'i', 'r' }. Like the split-index extension,
|
|
||||||
tools should avoid interacting with a sparse index unless they understand
|
|
||||||
this extension.
|
|
||||||
|
@ -43,9 +43,8 @@ Design Details
|
|||||||
a change in format.
|
a change in format.
|
||||||
|
|
||||||
- The MIDX keeps only one record per object ID. If an object appears
|
- The MIDX keeps only one record per object ID. If an object appears
|
||||||
in multiple packfiles, then the MIDX selects the copy in the
|
in multiple packfiles, then the MIDX selects the copy in the most-
|
||||||
preferred packfile, otherwise selecting from the most-recently
|
recently modified packfile.
|
||||||
modified packfile.
|
|
||||||
|
|
||||||
- If there exist packfiles in the pack directory not registered in
|
- If there exist packfiles in the pack directory not registered in
|
||||||
the MIDX, then those packfiles are loaded into the `packed_git`
|
the MIDX, then those packfiles are loaded into the `packed_git`
|
||||||
|
@ -379,86 +379,3 @@ CHUNK DATA:
|
|||||||
TRAILER:
|
TRAILER:
|
||||||
|
|
||||||
Index checksum of the above contents.
|
Index checksum of the above contents.
|
||||||
|
|
||||||
== multi-pack-index reverse indexes
|
|
||||||
|
|
||||||
Similar to the pack-based reverse index, the multi-pack index can also
|
|
||||||
be used to generate a reverse index.
|
|
||||||
|
|
||||||
Instead of mapping between offset, pack-, and index position, this
|
|
||||||
reverse index maps between an object's position within the MIDX, and
|
|
||||||
that object's position within a pseudo-pack that the MIDX describes
|
|
||||||
(i.e., the ith entry of the multi-pack reverse index holds the MIDX
|
|
||||||
position of ith object in pseudo-pack order).
|
|
||||||
|
|
||||||
To clarify the difference between these orderings, consider a multi-pack
|
|
||||||
reachability bitmap (which does not yet exist, but is what we are
|
|
||||||
building towards here). Each bit needs to correspond to an object in the
|
|
||||||
MIDX, and so we need an efficient mapping from bit position to MIDX
|
|
||||||
position.
|
|
||||||
|
|
||||||
One solution is to let bits occupy the same position in the oid-sorted
|
|
||||||
index stored by the MIDX. But because oids are effectively random, their
|
|
||||||
resulting reachability bitmaps would have no locality, and thus compress
|
|
||||||
poorly. (This is the reason that single-pack bitmaps use the pack
|
|
||||||
ordering, and not the .idx ordering, for the same purpose.)
|
|
||||||
|
|
||||||
So we'd like to define an ordering for the whole MIDX based around
|
|
||||||
pack ordering, which has far better locality (and thus compresses more
|
|
||||||
efficiently). We can think of a pseudo-pack created by the concatenation
|
|
||||||
of all of the packs in the MIDX. E.g., if we had a MIDX with three packs
|
|
||||||
(a, b, c), with 10, 15, and 20 objects respectively, we can imagine an
|
|
||||||
ordering of the objects like:
|
|
||||||
|
|
||||||
|a,0|a,1|...|a,9|b,0|b,1|...|b,14|c,0|c,1|...|c,19|
|
|
||||||
|
|
||||||
where the ordering of the packs is defined by the MIDX's pack list,
|
|
||||||
and then the ordering of objects within each pack is the same as the
|
|
||||||
order in the actual packfile.
|
|
||||||
|
|
||||||
Given the list of packs and their counts of objects, you can
|
|
||||||
naïvely reconstruct that pseudo-pack ordering (e.g., the object at
|
|
||||||
position 27 must be (c,1) because packs "a" and "b" consumed 25 of the
|
|
||||||
slots). But there's a catch. Objects may be duplicated between packs, in
|
|
||||||
which case the MIDX only stores one pointer to the object (and thus we'd
|
|
||||||
want only one slot in the bitmap).
|
|
||||||
|
|
||||||
Callers could handle duplicates themselves by reading objects in order
|
|
||||||
of their bit-position, but that's linear in the number of objects, and
|
|
||||||
much too expensive for ordinary bitmap lookups. Building a reverse index
|
|
||||||
solves this, since it is the logical inverse of the index, and that
|
|
||||||
index has already removed duplicates. But, building a reverse index on
|
|
||||||
the fly can be expensive. Since we already have an on-disk format for
|
|
||||||
pack-based reverse indexes, let's reuse it for the MIDX's pseudo-pack,
|
|
||||||
too.
|
|
||||||
|
|
||||||
Objects from the MIDX are ordered as follows to string together the
|
|
||||||
pseudo-pack. Let `pack(o)` return the pack from which `o` was selected
|
|
||||||
by the MIDX, and define an ordering of packs based on their numeric ID
|
|
||||||
(as stored by the MIDX). Let `offset(o)` return the object offset of `o`
|
|
||||||
within `pack(o)`. Then, compare `o1` and `o2` as follows:
|
|
||||||
|
|
||||||
- If one of `pack(o1)` and `pack(o2)` is preferred and the other
|
|
||||||
is not, then the preferred one sorts first.
|
|
||||||
+
|
|
||||||
(This is a detail that allows the MIDX bitmap to determine which
|
|
||||||
pack should be used by the pack-reuse mechanism, since it can ask
|
|
||||||
the MIDX for the pack containing the object at bit position 0).
|
|
||||||
|
|
||||||
- If `pack(o1) ≠ pack(o2)`, then sort the two objects in descending
|
|
||||||
order based on the pack ID.
|
|
||||||
|
|
||||||
- Otherwise, `pack(o1) = pack(o2)`, and the objects are sorted in
|
|
||||||
pack-order (i.e., `o1` sorts ahead of `o2` exactly when `offset(o1)
|
|
||||||
< offset(o2)`).
|
|
||||||
|
|
||||||
In short, a MIDX's pseudo-pack is the de-duplicated concatenation of
|
|
||||||
objects in packs stored by the MIDX, laid out in pack order, and the
|
|
||||||
packs arranged in MIDX order (with the preferred pack coming first).
|
|
||||||
|
|
||||||
Finally, note that the MIDX's reverse index is not stored as a chunk in
|
|
||||||
the multi-pack-index itself. This is done because the reverse index
|
|
||||||
includes the checksum of the pack or MIDX to which it belongs, which
|
|
||||||
makes it impossible to write in the MIDX. To avoid races when rewriting
|
|
||||||
the MIDX, a MIDX reverse index includes the MIDX's checksum in its
|
|
||||||
filename (e.g., `multi-pack-index-xyz.rev`).
|
|
||||||
|
@ -1,270 +0,0 @@
|
|||||||
Parallel Checkout Design Notes
|
|
||||||
==============================
|
|
||||||
|
|
||||||
The "Parallel Checkout" feature attempts to use multiple processes to
|
|
||||||
parallelize the work of uncompressing the blobs, applying in-core
|
|
||||||
filters, and writing the resulting contents to the working tree during a
|
|
||||||
checkout operation. It can be used by all checkout-related commands,
|
|
||||||
such as `clone`, `checkout`, `reset`, `sparse-checkout`, and others.
|
|
||||||
|
|
||||||
These commands share the following basic structure:
|
|
||||||
|
|
||||||
* Step 1: Read the current index file into memory.
|
|
||||||
|
|
||||||
* Step 2: Modify the in-memory index based upon the command, and
|
|
||||||
temporarily mark all cache entries that need to be updated.
|
|
||||||
|
|
||||||
* Step 3: Populate the working tree to match the new candidate index.
|
|
||||||
This includes iterating over all of the to-be-updated cache entries
|
|
||||||
and delete, create, or overwrite the associated files in the working
|
|
||||||
tree.
|
|
||||||
|
|
||||||
* Step 4: Write the new index to disk.
|
|
||||||
|
|
||||||
Step 3 is the focus of the "parallel checkout" effort described here.
|
|
||||||
|
|
||||||
Sequential Implementation
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
For the purposes of discussion here, the current sequential
|
|
||||||
implementation of Step 3 is divided in 3 parts, each one implemented in
|
|
||||||
its own function:
|
|
||||||
|
|
||||||
* Step 3a: `unpack-trees.c:check_updates()` contains a series of
|
|
||||||
sequential loops iterating over the `cache_entry`'s array. The main
|
|
||||||
loop in this function calls the Step 3b function for each of the
|
|
||||||
to-be-updated entries.
|
|
||||||
|
|
||||||
* Step 3b: `entry.c:checkout_entry()` examines the existing working tree
|
|
||||||
for file conflicts, collisions, and unsaved changes. It removes files
|
|
||||||
and creates leading directories as necessary. It calls the Step 3c
|
|
||||||
function for each entry to be written.
|
|
||||||
|
|
||||||
* Step 3c: `entry.c:write_entry()` loads the blob into memory, smudges
|
|
||||||
it if necessary, creates the file in the working tree, writes the
|
|
||||||
smudged contents, calls `fstat()` or `lstat()`, and updates the
|
|
||||||
associated `cache_entry` struct with the stat information gathered.
|
|
||||||
|
|
||||||
It wouldn't be safe to perform Step 3b in parallel, as there could be
|
|
||||||
race conditions between file creations and removals. Instead, the
|
|
||||||
parallel checkout framework lets the sequential code handle Step 3b,
|
|
||||||
and uses parallel workers to replace the sequential
|
|
||||||
`entry.c:write_entry()` calls from Step 3c.
|
|
||||||
|
|
||||||
Rejected Multi-Threaded Solution
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
The most "straightforward" implementation would be to spread the set of
|
|
||||||
to-be-updated cache entries across multiple threads. But due to the
|
|
||||||
thread-unsafe functions in the ODB code, we would have to use locks to
|
|
||||||
coordinate the parallel operation. An early prototype of this solution
|
|
||||||
showed that the multi-threaded checkout would bring performance
|
|
||||||
improvements over the sequential code, but there was still too much lock
|
|
||||||
contention. A `perf` profiling indicated that around 20% of the runtime
|
|
||||||
during a local Linux clone (on an SSD) was spent in locking functions.
|
|
||||||
For this reason this approach was rejected in favor of using multiple
|
|
||||||
child processes, which led to a better performance.
|
|
||||||
|
|
||||||
Multi-Process Solution
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Parallel checkout alters the aforementioned Step 3 to use multiple
|
|
||||||
`checkout--worker` background processes to distribute the work. The
|
|
||||||
long-running worker processes are controlled by the foreground Git
|
|
||||||
command using the existing run-command API.
|
|
||||||
|
|
||||||
Overview
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
Step 3b is only slightly altered; for each entry to be checked out, the
|
|
||||||
main process performs the following steps:
|
|
||||||
|
|
||||||
* M1: Check whether there is any untracked or unclean file in the
|
|
||||||
working tree which would be overwritten by this entry, and decide
|
|
||||||
whether to proceed (removing the file(s)) or not.
|
|
||||||
|
|
||||||
* M2: Create the leading directories.
|
|
||||||
|
|
||||||
* M3: Load the conversion attributes for the entry's path.
|
|
||||||
|
|
||||||
* M4: Check, based on the entry's type and conversion attributes,
|
|
||||||
whether the entry is eligible for parallel checkout (more on this
|
|
||||||
later). If it is eligible, enqueue the entry and the loaded
|
|
||||||
attributes to later write the entry in parallel. If not, write the
|
|
||||||
entry right away, using the default sequential code.
|
|
||||||
|
|
||||||
Note: we save the conversion attributes associated with each entry
|
|
||||||
because the workers don't have access to the main process' index state,
|
|
||||||
so they can't load the attributes by themselves (and the attributes are
|
|
||||||
needed to properly smudge the entry). Additionally, this has a positive
|
|
||||||
impact on performance as (1) we don't need to load the attributes twice
|
|
||||||
and (2) the attributes machinery is optimized to handle paths in
|
|
||||||
sequential order.
|
|
||||||
|
|
||||||
After all entries have passed through the above steps, the main process
|
|
||||||
checks if the number of enqueued entries is sufficient to spread among
|
|
||||||
the workers. If not, it just writes them sequentially. Otherwise, it
|
|
||||||
spawns the workers and distributes the queued entries uniformly in
|
|
||||||
continuous chunks. This aims to minimize the chances of two workers
|
|
||||||
writing to the same directory simultaneously, which could increase lock
|
|
||||||
contention in the kernel.
|
|
||||||
|
|
||||||
Then, for each assigned item, each worker:
|
|
||||||
|
|
||||||
* W1: Checks if there is any non-directory file in the leading part of
|
|
||||||
the entry's path or if there already exists a file at the entry' path.
|
|
||||||
If so, mark the entry with `PC_ITEM_COLLIDED` and skip it (more on
|
|
||||||
this later).
|
|
||||||
|
|
||||||
* W2: Creates the file (with O_CREAT and O_EXCL).
|
|
||||||
|
|
||||||
* W3: Loads the blob into memory (inflating and delta reconstructing
|
|
||||||
it).
|
|
||||||
|
|
||||||
* W4: Applies any required in-process filter, like end-of-line
|
|
||||||
conversion and re-encoding.
|
|
||||||
|
|
||||||
* W5: Writes the result to the file descriptor opened at W2.
|
|
||||||
|
|
||||||
* W6: Calls `fstat()` or lstat()` on the just-written path, and sends
|
|
||||||
the result back to the main process, together with the end status of
|
|
||||||
the operation and the item's identification number.
|
|
||||||
|
|
||||||
Note that, when possible, steps W3 to W5 are delegated to the streaming
|
|
||||||
machinery, removing the need to keep the entire blob in memory.
|
|
||||||
|
|
||||||
If the worker fails to read the blob or to write it to the working tree,
|
|
||||||
it removes the created file to avoid leaving empty files behind. This is
|
|
||||||
the *only* time a worker is allowed to remove a file.
|
|
||||||
|
|
||||||
As mentioned earlier, it is the responsibility of the main process to
|
|
||||||
remove any file that blocks the checkout operation (or abort if the
|
|
||||||
removal(s) would cause data loss and the user didn't ask to `--force`).
|
|
||||||
This is crucial to avoid race conditions and also to properly detect
|
|
||||||
path collisions at Step W1.
|
|
||||||
|
|
||||||
After the workers finish writing the items and sending back the required
|
|
||||||
information, the main process handles the results in two steps:
|
|
||||||
|
|
||||||
- First, it updates the in-memory index with the `lstat()` information
|
|
||||||
sent by the workers. (This must be done first as this information
|
|
||||||
might me required in the following step.)
|
|
||||||
|
|
||||||
- Then it writes the items which collided on disk (i.e. items marked
|
|
||||||
with `PC_ITEM_COLLIDED`). More on this below.
|
|
||||||
|
|
||||||
Path Collisions
|
|
||||||
---------------
|
|
||||||
|
|
||||||
Path collisions happen when two different paths correspond to the same
|
|
||||||
entry in the file system. E.g. the paths 'a' and 'A' would collide in a
|
|
||||||
case-insensitive file system.
|
|
||||||
|
|
||||||
The sequential checkout deals with collisions in the same way that it
|
|
||||||
deals with files that were already present in the working tree before
|
|
||||||
checkout. Basically, it checks if the path that it wants to write
|
|
||||||
already exists on disk, makes sure the existing file doesn't have
|
|
||||||
unsaved data, and then overwrites it. (To be more pedantic: it deletes
|
|
||||||
the existing file and creates the new one.) So, if there are multiple
|
|
||||||
colliding files to be checked out, the sequential code will write each
|
|
||||||
one of them but only the last will actually survive on disk.
|
|
||||||
|
|
||||||
Parallel checkout aims to reproduce the same behavior. However, we
|
|
||||||
cannot let the workers racily write to the same file on disk. Instead,
|
|
||||||
the workers detect when the entry that they want to check out would
|
|
||||||
collide with an existing file, and mark it with `PC_ITEM_COLLIDED`.
|
|
||||||
Later, the main process can sequentially feed these entries back to
|
|
||||||
`checkout_entry()` without the risk of race conditions. On clone, this
|
|
||||||
also has the effect of marking the colliding entries to later emit a
|
|
||||||
warning for the user, like the classic sequential checkout does.
|
|
||||||
|
|
||||||
The workers are able to detect both collisions among the entries being
|
|
||||||
concurrently written and collisions between a parallel-eligible entry
|
|
||||||
and an ineligible entry. The general idea for collision detection is
|
|
||||||
quite straightforward: for each parallel-eligible entry, the main
|
|
||||||
process must remove all files that prevent this entry from being written
|
|
||||||
(before enqueueing it). This includes any non-directory file in the
|
|
||||||
leading path of the entry. Later, when a worker gets assigned the entry,
|
|
||||||
it looks again for the non-directories files and for an already existing
|
|
||||||
file at the entry's path. If any of these checks finds something, the
|
|
||||||
worker knows that there was a path collision.
|
|
||||||
|
|
||||||
Because parallel checkout can distinguish path collisions from the case
|
|
||||||
where the file was already present in the working tree before checkout,
|
|
||||||
we could alternatively choose to skip the checkout of colliding entries.
|
|
||||||
However, each entry that doesn't get written would have NULL `lstat()`
|
|
||||||
fields on the index. This could cause performance penalties for
|
|
||||||
subsequent commands that need to refresh the index, as they would have
|
|
||||||
to go to the file system to see if the entry is dirty. Thus, if we have
|
|
||||||
N entries in a colliding group and we decide to write and `lstat()` only
|
|
||||||
one of them, every subsequent `git-status` will have to read, convert,
|
|
||||||
and hash the written file N - 1 times. By checking out all colliding
|
|
||||||
entries (like the sequential code does), we only pay the overhead once,
|
|
||||||
during checkout.
|
|
||||||
|
|
||||||
Eligible Entries for Parallel Checkout
|
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
As previously mentioned, not all entries passed to `checkout_entry()`
|
|
||||||
will be considered eligible for parallel checkout. More specifically, we
|
|
||||||
exclude:
|
|
||||||
|
|
||||||
- Symbolic links; to avoid race conditions that, in combination with
|
|
||||||
path collisions, could cause workers to write files at the wrong
|
|
||||||
place. For example, if we were to concurrently check out a symlink
|
|
||||||
'a' -> 'b' and a regular file 'A/f' in a case-insensitive file system,
|
|
||||||
we could potentially end up writing the file 'A/f' at 'a/f', due to a
|
|
||||||
race condition.
|
|
||||||
|
|
||||||
- Regular files that require external filters (either "one shot" filters
|
|
||||||
or long-running process filters). These filters are black-boxes to Git
|
|
||||||
and may have their own internal locking or non-concurrent assumptions.
|
|
||||||
So it might not be safe to run multiple instances in parallel.
|
|
||||||
+
|
|
||||||
Besides, long-running filters may use the delayed checkout feature to
|
|
||||||
postpone the return of some filtered blobs. The delayed checkout queue
|
|
||||||
and the parallel checkout queue are not compatible and should remain
|
|
||||||
separate.
|
|
||||||
+
|
|
||||||
Note: regular files that only require internal filters, like end-of-line
|
|
||||||
conversion and re-encoding, are eligible for parallel checkout.
|
|
||||||
|
|
||||||
Ineligible entries are checked out by the classic sequential codepath
|
|
||||||
*before* spawning workers.
|
|
||||||
|
|
||||||
Note: submodules's files are also eligible for parallel checkout (as
|
|
||||||
long as they don't fall into any of the excluding categories mentioned
|
|
||||||
above). But since each submodule is checked out in its own child
|
|
||||||
process, we don't mix the superproject's and the submodules' files in
|
|
||||||
the same parallel checkout process or queue.
|
|
||||||
|
|
||||||
The API
|
|
||||||
-------
|
|
||||||
|
|
||||||
The parallel checkout API was designed with the goal of minimizing
|
|
||||||
changes to the current users of the checkout machinery. This means that
|
|
||||||
they don't have to call a different function for sequential or parallel
|
|
||||||
checkout. As already mentioned, `checkout_entry()` will automatically
|
|
||||||
insert the given entry in the parallel checkout queue when this feature
|
|
||||||
is enabled and the entry is eligible; otherwise, it will just write the
|
|
||||||
entry right away, using the sequential code. In general, callers of the
|
|
||||||
parallel checkout API should look similar to this:
|
|
||||||
|
|
||||||
----------------------------------------------
|
|
||||||
int pc_workers, pc_threshold, err = 0;
|
|
||||||
struct checkout state;
|
|
||||||
|
|
||||||
get_parallel_checkout_configs(&pc_workers, &pc_threshold);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This check is not strictly required, but it
|
|
||||||
* should save some time in sequential mode.
|
|
||||||
*/
|
|
||||||
if (pc_workers > 1)
|
|
||||||
init_parallel_checkout();
|
|
||||||
|
|
||||||
for (each cache_entry ce to-be-updated)
|
|
||||||
err |= checkout_entry(ce, &state, NULL, NULL);
|
|
||||||
|
|
||||||
err |= run_parallel_checkout(&state, pc_workers, pc_threshold, NULL, NULL);
|
|
||||||
----------------------------------------------
|
|
@ -346,14 +346,6 @@ explained below.
|
|||||||
client should download from all given URIs. Currently, the
|
client should download from all given URIs. Currently, the
|
||||||
protocols supported are "http" and "https".
|
protocols supported are "http" and "https".
|
||||||
|
|
||||||
If the 'wait-for-done' feature is advertised, the following argument
|
|
||||||
can be included in the client's request.
|
|
||||||
|
|
||||||
wait-for-done
|
|
||||||
Indicates to the server that it should never send "ready", but
|
|
||||||
should wait for the client to say "done" before sending the
|
|
||||||
packfile.
|
|
||||||
|
|
||||||
The response of `fetch` is broken into a number of sections separated by
|
The response of `fetch` is broken into a number of sections separated by
|
||||||
delimiter packets (0001), with each section beginning with its section
|
delimiter packets (0001), with each section beginning with its section
|
||||||
header. Most sections are sent only when the packfile is sent.
|
header. Most sections are sent only when the packfile is sent.
|
||||||
@ -522,34 +514,3 @@ packet-line, and must not contain non-printable or whitespace characters. The
|
|||||||
current implementation uses trace2 session IDs (see
|
current implementation uses trace2 session IDs (see
|
||||||
link:api-trace2.html[api-trace2] for details), but this may change and users of
|
link:api-trace2.html[api-trace2] for details), but this may change and users of
|
||||||
the session ID should not rely on this fact.
|
the session ID should not rely on this fact.
|
||||||
|
|
||||||
object-info
|
|
||||||
~~~~~~~~~~~
|
|
||||||
|
|
||||||
`object-info` is the command to retrieve information about one or more objects.
|
|
||||||
Its main purpose is to allow a client to make decisions based on this
|
|
||||||
information without having to fully fetch objects. Object size is the only
|
|
||||||
information that is currently supported.
|
|
||||||
|
|
||||||
An `object-info` request takes the following arguments:
|
|
||||||
|
|
||||||
size
|
|
||||||
Requests size information to be returned for each listed object id.
|
|
||||||
|
|
||||||
oid <oid>
|
|
||||||
Indicates to the server an object which the client wants to obtain
|
|
||||||
information for.
|
|
||||||
|
|
||||||
The response of `object-info` is a list of the the requested object ids
|
|
||||||
and associated requested information, each separated by a single space.
|
|
||||||
|
|
||||||
output = info flush-pkt
|
|
||||||
|
|
||||||
info = PKT-LINE(attrs) LF)
|
|
||||||
*PKT-LINE(obj-info LF)
|
|
||||||
|
|
||||||
attrs = attr | attrs SP attrs
|
|
||||||
|
|
||||||
attr = "size"
|
|
||||||
|
|
||||||
obj-info = obj-id SP obj-size
|
|
||||||
|
@ -1011,13 +1011,8 @@ reftable stack, reload `tables.list`, and delete any tables no longer mentioned
|
|||||||
in `tables.list`.
|
in `tables.list`.
|
||||||
|
|
||||||
Irregular program exit may still leave about unused files. In this case, a
|
Irregular program exit may still leave about unused files. In this case, a
|
||||||
cleanup operation should proceed as follows:
|
cleanup operation can read `tables.list`, note its modification timestamp, and
|
||||||
|
delete any unreferenced `*.ref` files that are older.
|
||||||
* take a lock `tables.list.lock` to prevent concurrent modifications
|
|
||||||
* refresh the reftable stack, by reading `tables.list`
|
|
||||||
* for each `*.ref` file, remove it if
|
|
||||||
** it is not mentioned in `tables.list`, and
|
|
||||||
** its max update_index is not beyond the max update_index of the stack
|
|
||||||
|
|
||||||
|
|
||||||
Alternatives considered
|
Alternatives considered
|
||||||
|
@ -1,208 +0,0 @@
|
|||||||
Git Sparse-Index Design Document
|
|
||||||
================================
|
|
||||||
|
|
||||||
The sparse-checkout feature allows users to focus a working directory on
|
|
||||||
a subset of the files at HEAD. The cone mode patterns, enabled by
|
|
||||||
`core.sparseCheckoutCone`, allow for very fast pattern matching to
|
|
||||||
discover which files at HEAD belong in the sparse-checkout cone.
|
|
||||||
|
|
||||||
Three important scale dimensions for a Git working directory are:
|
|
||||||
|
|
||||||
* `HEAD`: How many files are present at `HEAD`?
|
|
||||||
|
|
||||||
* Populated: How many files are within the sparse-checkout cone.
|
|
||||||
|
|
||||||
* Modified: How many files has the user modified in the working directory?
|
|
||||||
|
|
||||||
We will use big-O notation -- O(X) -- to denote how expensive certain
|
|
||||||
operations are in terms of these dimensions.
|
|
||||||
|
|
||||||
These dimensions are ordered by their magnitude: users (typically) modify
|
|
||||||
fewer files than are populated, and we can only populate files at `HEAD`.
|
|
||||||
|
|
||||||
Problems occur if there is an extreme imbalance in these dimensions. For
|
|
||||||
example, if `HEAD` contains millions of paths but the populated set has
|
|
||||||
only tens of thousands, then commands like `git status` and `git add` can
|
|
||||||
be dominated by operations that require O(`HEAD`) operations instead of
|
|
||||||
O(Populated). Primarily, the cost is in parsing and rewriting the index,
|
|
||||||
which is filled primarily with files at `HEAD` that are marked with the
|
|
||||||
`SKIP_WORKTREE` bit.
|
|
||||||
|
|
||||||
The sparse-index intends to take these commands that read and modify the
|
|
||||||
index from O(`HEAD`) to O(Populated). To do this, we need to modify the
|
|
||||||
index format in a significant way: add "sparse directory" entries.
|
|
||||||
|
|
||||||
With cone mode patterns, it is possible to detect when an entire
|
|
||||||
directory will have its contents outside of the sparse-checkout definition.
|
|
||||||
Instead of listing all of the files it contains as individual entries, a
|
|
||||||
sparse-index contains an entry with the directory name, referencing the
|
|
||||||
object ID of the tree at `HEAD` and marked with the `SKIP_WORKTREE` bit.
|
|
||||||
If we need to discover the details for paths within that directory, we
|
|
||||||
can parse trees to find that list.
|
|
||||||
|
|
||||||
At time of writing, sparse-directory entries violate expectations about the
|
|
||||||
index format and its in-memory data structure. There are many consumers in
|
|
||||||
the codebase that expect to iterate through all of the index entries and
|
|
||||||
see only files. In fact, these loops expect to see a reference to every
|
|
||||||
staged file. One way to handle this is to parse trees to replace a
|
|
||||||
sparse-directory entry with all of the files within that tree as the index
|
|
||||||
is loaded. However, parsing trees is slower than parsing the index format,
|
|
||||||
so that is a slower operation than if we left the index alone. The plan is
|
|
||||||
to make all of these integrations "sparse aware" so this expansion through
|
|
||||||
tree parsing is unnecessary and they use fewer resources than when using a
|
|
||||||
full index.
|
|
||||||
|
|
||||||
The implementation plan below follows four phases to slowly integrate with
|
|
||||||
the sparse-index. The intention is to incrementally update Git commands to
|
|
||||||
interact safely with the sparse-index without significant slowdowns. This
|
|
||||||
may not always be possible, but the hope is that the primary commands that
|
|
||||||
users need in their daily work are dramatically improved.
|
|
||||||
|
|
||||||
Phase I: Format and initial speedups
|
|
||||||
------------------------------------
|
|
||||||
|
|
||||||
During this phase, Git learns to enable the sparse-index and safely parse
|
|
||||||
one. Protections are put in place so that every consumer of the in-memory
|
|
||||||
data structure can operate with its current assumption of every file at
|
|
||||||
`HEAD`.
|
|
||||||
|
|
||||||
At first, every index parse will call a helper method,
|
|
||||||
`ensure_full_index()`, which scans the index for sparse-directory entries
|
|
||||||
(pointing to trees) and replaces them with the full list of paths (with
|
|
||||||
blob contents) by parsing tree objects. This will be slower in all cases.
|
|
||||||
The only noticeable change in behavior will be that the serialized index
|
|
||||||
file contains sparse-directory entries.
|
|
||||||
|
|
||||||
To start, we use a new required index extension, `sdir`, to allow
|
|
||||||
inserting sparse-directory entries into indexes with file format
|
|
||||||
versions 2, 3, and 4. This prevents Git versions that do not understand
|
|
||||||
the sparse-index from operating on one, while allowing tools that do not
|
|
||||||
understand the sparse-index to operate on repositories as long as they do
|
|
||||||
not interact with the index. A new format, index v5, will be introduced
|
|
||||||
that includes sparse-directory entries by default. It might also
|
|
||||||
introduce other features that have been considered for improving the
|
|
||||||
index, as well.
|
|
||||||
|
|
||||||
Next, consumers of the index will be guarded against operating on a
|
|
||||||
sparse-index by inserting calls to `ensure_full_index()` or
|
|
||||||
`expand_index_to_path()`. If a specific path is requested, then those will
|
|
||||||
be protected from within the `index_file_exists()` and `index_name_pos()`
|
|
||||||
API calls: they will call `ensure_full_index()` if necessary. The
|
|
||||||
intention here is to preserve existing behavior when interacting with a
|
|
||||||
sparse-checkout. We don't want a change to happen by accident, without
|
|
||||||
tests. Many of these locations may not need any change before removing the
|
|
||||||
guards, but we should not do so without tests to ensure the expected
|
|
||||||
behavior happens.
|
|
||||||
|
|
||||||
It may be desirable to _change_ the behavior of some commands in the
|
|
||||||
presence of a sparse index or more generally in any sparse-checkout
|
|
||||||
scenario. In such cases, these should be carefully communicated and
|
|
||||||
tested. No such behavior changes are intended during this phase.
|
|
||||||
|
|
||||||
During a scan of the codebase, not every iteration of the cache entries
|
|
||||||
needs an `ensure_full_index()` check. The basic reasons include:
|
|
||||||
|
|
||||||
1. The loop is scanning for entries with non-zero stage. These entries
|
|
||||||
are not collapsed into a sparse-directory entry.
|
|
||||||
|
|
||||||
2. The loop is scanning for submodules. These entries are not collapsed
|
|
||||||
into a sparse-directory entry.
|
|
||||||
|
|
||||||
3. The loop is part of the index API, especially around reading or
|
|
||||||
writing the format.
|
|
||||||
|
|
||||||
4. The loop is checking for correct order of cache entries and that is
|
|
||||||
correct if and only if the sparse-directory entries are in the correct
|
|
||||||
location.
|
|
||||||
|
|
||||||
5. The loop ignores entries with the `SKIP_WORKTREE` bit set, or is
|
|
||||||
otherwise already aware of sparse directory entries.
|
|
||||||
|
|
||||||
6. The sparse-index is disabled at this point when using the split-index
|
|
||||||
feature, so no effort is made to protect the split-index API.
|
|
||||||
|
|
||||||
Even after inserting these guards, we will keep expanding sparse-indexes
|
|
||||||
for most Git commands using the `command_requires_full_index` repository
|
|
||||||
setting. This setting will be on by default and disabled one builtin at a
|
|
||||||
time until we have sufficient confidence that all of the index operations
|
|
||||||
are properly guarded.
|
|
||||||
|
|
||||||
To complete this phase, the commands `git status` and `git add` will be
|
|
||||||
integrated with the sparse-index so that they operate with O(Populated)
|
|
||||||
performance. They will be carefully tested for operations within and
|
|
||||||
outside the sparse-checkout definition.
|
|
||||||
|
|
||||||
Phase II: Careful integrations
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
This phase focuses on ensuring that all index extensions and APIs work
|
|
||||||
well with a sparse-index. This requires significant increases to our test
|
|
||||||
coverage, especially for operations that interact with the working
|
|
||||||
directory outside of the sparse-checkout definition. Some of these
|
|
||||||
behaviors may not be the desirable ones, such as some tests already
|
|
||||||
marked for failure in `t1092-sparse-checkout-compatibility.sh`.
|
|
||||||
|
|
||||||
The index extensions that may require special integrations are:
|
|
||||||
|
|
||||||
* FS Monitor
|
|
||||||
* Untracked cache
|
|
||||||
|
|
||||||
While integrating with these features, we should look for patterns that
|
|
||||||
might lead to better APIs for interacting with the index. Coalescing
|
|
||||||
common usage patterns into an API call can reduce the number of places
|
|
||||||
where sparse-directories need to be handled carefully.
|
|
||||||
|
|
||||||
Phase III: Important command speedups
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
At this point, the patterns for testing and implementing sparse-directory
|
|
||||||
logic should be relatively stable. This phase focuses on updating some of
|
|
||||||
the most common builtins that use the index to operate as O(Populated).
|
|
||||||
Here is a potential list of commands that could be valuable to integrate
|
|
||||||
at this point:
|
|
||||||
|
|
||||||
* `git commit`
|
|
||||||
* `git checkout`
|
|
||||||
* `git merge`
|
|
||||||
* `git rebase`
|
|
||||||
|
|
||||||
Hopefully, commands such as `git merge` and `git rebase` can benefit
|
|
||||||
instead from merge algorithms that do not use the index as a data
|
|
||||||
structure, such as the merge-ORT strategy. As these topics mature, we
|
|
||||||
may enable the ORT strategy by default for repositories using the
|
|
||||||
sparse-index feature.
|
|
||||||
|
|
||||||
Along with `git status` and `git add`, these commands cover the majority
|
|
||||||
of users' interactions with the working directory. In addition, we can
|
|
||||||
integrate with these commands:
|
|
||||||
|
|
||||||
* `git grep`
|
|
||||||
* `git rm`
|
|
||||||
|
|
||||||
These have been proposed as some whose behavior could change when in a
|
|
||||||
repo with a sparse-checkout definition. It would be good to include this
|
|
||||||
behavior automatically when using a sparse-index. Some clarity is needed
|
|
||||||
to make the behavior switch clear to the user.
|
|
||||||
|
|
||||||
This phase is the first where parallel work might be possible without too
|
|
||||||
much conflicts between topics.
|
|
||||||
|
|
||||||
Phase IV: The long tail
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
This last phase is less a "phase" and more "the new normal" after all of
|
|
||||||
the previous work.
|
|
||||||
|
|
||||||
To start, the `command_requires_full_index` option could be removed in
|
|
||||||
favor of expanding only when hitting an API guard.
|
|
||||||
|
|
||||||
There are many Git commands that could use special attention to operate as
|
|
||||||
O(Populated), while some might be so rare that it is acceptable to leave
|
|
||||||
them with additional overhead when a sparse-index is present.
|
|
||||||
|
|
||||||
Here are some commands that might be useful to update:
|
|
||||||
|
|
||||||
* `git sparse-checkout set`
|
|
||||||
* `git am`
|
|
||||||
* `git clean`
|
|
||||||
* `git stash`
|
|
@ -1,8 +1,5 @@
|
|||||||
= Git User Manual
|
= Git User Manual
|
||||||
|
|
||||||
[preface]
|
|
||||||
== Introduction
|
|
||||||
|
|
||||||
Git is a fast distributed revision control system.
|
Git is a fast distributed revision control system.
|
||||||
|
|
||||||
This manual is designed to be readable by someone with basic UNIX
|
This manual is designed to be readable by someone with basic UNIX
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
GVF=GIT-VERSION-FILE
|
GVF=GIT-VERSION-FILE
|
||||||
DEF_VER=v2.32.4
|
DEF_VER=v2.31.6
|
||||||
|
|
||||||
LF='
|
LF='
|
||||||
'
|
'
|
||||||
|
4
INSTALL
4
INSTALL
@ -197,9 +197,7 @@ Issues of note:
|
|||||||
Building and installing the pdf file additionally requires
|
Building and installing the pdf file additionally requires
|
||||||
dblatex. Version >= 0.2.7 is known to work.
|
dblatex. Version >= 0.2.7 is known to work.
|
||||||
|
|
||||||
All formats require at least asciidoc 8.4.1. Alternatively, you can
|
All formats require at least asciidoc 8.4.1.
|
||||||
use Asciidoctor (requires Ruby) by passing USE_ASCIIDOCTOR=YesPlease
|
|
||||||
to make. You need at least Asciidoctor version 1.5.
|
|
||||||
|
|
||||||
There are also "make quick-install-doc", "make quick-install-man"
|
There are also "make quick-install-doc", "make quick-install-man"
|
||||||
and "make quick-install-html" which install preformatted man pages
|
and "make quick-install-html" which install preformatted man pages
|
||||||
|
91
Makefile
91
Makefile
@ -578,9 +578,7 @@ GENERATED_H =
|
|||||||
EXTRA_CPPFLAGS =
|
EXTRA_CPPFLAGS =
|
||||||
FUZZ_OBJS =
|
FUZZ_OBJS =
|
||||||
FUZZ_PROGRAMS =
|
FUZZ_PROGRAMS =
|
||||||
GIT_OBJS =
|
|
||||||
LIB_OBJS =
|
LIB_OBJS =
|
||||||
OBJECTS =
|
|
||||||
PROGRAM_OBJS =
|
PROGRAM_OBJS =
|
||||||
PROGRAMS =
|
PROGRAMS =
|
||||||
EXCLUDED_PROGRAMS =
|
EXCLUDED_PROGRAMS =
|
||||||
@ -589,7 +587,6 @@ SCRIPT_PYTHON =
|
|||||||
SCRIPT_SH =
|
SCRIPT_SH =
|
||||||
SCRIPT_LIB =
|
SCRIPT_LIB =
|
||||||
TEST_BUILTINS_OBJS =
|
TEST_BUILTINS_OBJS =
|
||||||
TEST_OBJS =
|
|
||||||
TEST_PROGRAMS_NEED_X =
|
TEST_PROGRAMS_NEED_X =
|
||||||
THIRD_PARTY_SOURCES =
|
THIRD_PARTY_SOURCES =
|
||||||
|
|
||||||
@ -665,8 +662,6 @@ ETAGS_TARGET = TAGS
|
|||||||
FUZZ_OBJS += fuzz-commit-graph.o
|
FUZZ_OBJS += fuzz-commit-graph.o
|
||||||
FUZZ_OBJS += fuzz-pack-headers.o
|
FUZZ_OBJS += fuzz-pack-headers.o
|
||||||
FUZZ_OBJS += fuzz-pack-idx.o
|
FUZZ_OBJS += fuzz-pack-idx.o
|
||||||
.PHONY: fuzz-objs
|
|
||||||
fuzz-objs: $(FUZZ_OBJS)
|
|
||||||
|
|
||||||
# Always build fuzz objects even if not testing, to prevent bit-rot.
|
# Always build fuzz objects even if not testing, to prevent bit-rot.
|
||||||
all:: $(FUZZ_OBJS)
|
all:: $(FUZZ_OBJS)
|
||||||
@ -684,8 +679,6 @@ PROGRAM_OBJS += http-backend.o
|
|||||||
PROGRAM_OBJS += imap-send.o
|
PROGRAM_OBJS += imap-send.o
|
||||||
PROGRAM_OBJS += sh-i18n--envsubst.o
|
PROGRAM_OBJS += sh-i18n--envsubst.o
|
||||||
PROGRAM_OBJS += shell.o
|
PROGRAM_OBJS += shell.o
|
||||||
.PHONY: program-objs
|
|
||||||
program-objs: $(PROGRAM_OBJS)
|
|
||||||
|
|
||||||
# Binary suffix, set to .exe for Windows builds
|
# Binary suffix, set to .exe for Windows builds
|
||||||
X =
|
X =
|
||||||
@ -693,7 +686,6 @@ X =
|
|||||||
PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
|
PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
|
||||||
|
|
||||||
TEST_BUILTINS_OBJS += test-advise.o
|
TEST_BUILTINS_OBJS += test-advise.o
|
||||||
TEST_BUILTINS_OBJS += test-bitmap.o
|
|
||||||
TEST_BUILTINS_OBJS += test-bloom.o
|
TEST_BUILTINS_OBJS += test-bloom.o
|
||||||
TEST_BUILTINS_OBJS += test-chmtime.o
|
TEST_BUILTINS_OBJS += test-chmtime.o
|
||||||
TEST_BUILTINS_OBJS += test-config.o
|
TEST_BUILTINS_OBJS += test-config.o
|
||||||
@ -745,7 +737,6 @@ TEST_BUILTINS_OBJS += test-serve-v2.o
|
|||||||
TEST_BUILTINS_OBJS += test-sha1.o
|
TEST_BUILTINS_OBJS += test-sha1.o
|
||||||
TEST_BUILTINS_OBJS += test-sha256.o
|
TEST_BUILTINS_OBJS += test-sha256.o
|
||||||
TEST_BUILTINS_OBJS += test-sigchain.o
|
TEST_BUILTINS_OBJS += test-sigchain.o
|
||||||
TEST_BUILTINS_OBJS += test-simple-ipc.o
|
|
||||||
TEST_BUILTINS_OBJS += test-strcmp-offset.o
|
TEST_BUILTINS_OBJS += test-strcmp-offset.o
|
||||||
TEST_BUILTINS_OBJS += test-string-list.o
|
TEST_BUILTINS_OBJS += test-string-list.o
|
||||||
TEST_BUILTINS_OBJS += test-submodule-config.o
|
TEST_BUILTINS_OBJS += test-submodule-config.o
|
||||||
@ -753,7 +744,6 @@ TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o
|
|||||||
TEST_BUILTINS_OBJS += test-subprocess.o
|
TEST_BUILTINS_OBJS += test-subprocess.o
|
||||||
TEST_BUILTINS_OBJS += test-trace2.o
|
TEST_BUILTINS_OBJS += test-trace2.o
|
||||||
TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
|
TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
|
||||||
TEST_BUILTINS_OBJS += test-userdiff.o
|
|
||||||
TEST_BUILTINS_OBJS += test-wildmatch.o
|
TEST_BUILTINS_OBJS += test-wildmatch.o
|
||||||
TEST_BUILTINS_OBJS += test-windows-named-pipe.o
|
TEST_BUILTINS_OBJS += test-windows-named-pipe.o
|
||||||
TEST_BUILTINS_OBJS += test-write-cache.o
|
TEST_BUILTINS_OBJS += test-write-cache.o
|
||||||
@ -948,7 +938,6 @@ LIB_OBJS += pack-revindex.o
|
|||||||
LIB_OBJS += pack-write.o
|
LIB_OBJS += pack-write.o
|
||||||
LIB_OBJS += packfile.o
|
LIB_OBJS += packfile.o
|
||||||
LIB_OBJS += pager.o
|
LIB_OBJS += pager.o
|
||||||
LIB_OBJS += parallel-checkout.o
|
|
||||||
LIB_OBJS += parse-options-cb.o
|
LIB_OBJS += parse-options-cb.o
|
||||||
LIB_OBJS += parse-options.o
|
LIB_OBJS += parse-options.o
|
||||||
LIB_OBJS += patch-delta.o
|
LIB_OBJS += patch-delta.o
|
||||||
@ -963,7 +952,6 @@ LIB_OBJS += progress.o
|
|||||||
LIB_OBJS += promisor-remote.o
|
LIB_OBJS += promisor-remote.o
|
||||||
LIB_OBJS += prompt.o
|
LIB_OBJS += prompt.o
|
||||||
LIB_OBJS += protocol.o
|
LIB_OBJS += protocol.o
|
||||||
LIB_OBJS += protocol-caps.o
|
|
||||||
LIB_OBJS += prune-packed.o
|
LIB_OBJS += prune-packed.o
|
||||||
LIB_OBJS += quote.o
|
LIB_OBJS += quote.o
|
||||||
LIB_OBJS += range-diff.o
|
LIB_OBJS += range-diff.o
|
||||||
@ -997,7 +985,6 @@ LIB_OBJS += setup.o
|
|||||||
LIB_OBJS += shallow.o
|
LIB_OBJS += shallow.o
|
||||||
LIB_OBJS += sideband.o
|
LIB_OBJS += sideband.o
|
||||||
LIB_OBJS += sigchain.o
|
LIB_OBJS += sigchain.o
|
||||||
LIB_OBJS += sparse-index.o
|
|
||||||
LIB_OBJS += split-index.o
|
LIB_OBJS += split-index.o
|
||||||
LIB_OBJS += stable-qsort.o
|
LIB_OBJS += stable-qsort.o
|
||||||
LIB_OBJS += strbuf.o
|
LIB_OBJS += strbuf.o
|
||||||
@ -1066,7 +1053,6 @@ BUILTIN_OBJS += builtin/check-attr.o
|
|||||||
BUILTIN_OBJS += builtin/check-ignore.o
|
BUILTIN_OBJS += builtin/check-ignore.o
|
||||||
BUILTIN_OBJS += builtin/check-mailmap.o
|
BUILTIN_OBJS += builtin/check-mailmap.o
|
||||||
BUILTIN_OBJS += builtin/check-ref-format.o
|
BUILTIN_OBJS += builtin/check-ref-format.o
|
||||||
BUILTIN_OBJS += builtin/checkout--worker.o
|
|
||||||
BUILTIN_OBJS += builtin/checkout-index.o
|
BUILTIN_OBJS += builtin/checkout-index.o
|
||||||
BUILTIN_OBJS += builtin/checkout.o
|
BUILTIN_OBJS += builtin/checkout.o
|
||||||
BUILTIN_OBJS += builtin/clean.o
|
BUILTIN_OBJS += builtin/clean.o
|
||||||
@ -1686,32 +1672,6 @@ ifdef NO_UNIX_SOCKETS
|
|||||||
BASIC_CFLAGS += -DNO_UNIX_SOCKETS
|
BASIC_CFLAGS += -DNO_UNIX_SOCKETS
|
||||||
else
|
else
|
||||||
LIB_OBJS += unix-socket.o
|
LIB_OBJS += unix-socket.o
|
||||||
LIB_OBJS += unix-stream-server.o
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Simple IPC requires threads and platform-specific IPC support.
|
|
||||||
# Only platforms that have both should include these source files
|
|
||||||
# in the build.
|
|
||||||
#
|
|
||||||
# On Windows-based systems, Simple IPC requires threads and Windows
|
|
||||||
# Named Pipes. These are always available, so Simple IPC support
|
|
||||||
# is optional.
|
|
||||||
#
|
|
||||||
# On Unix-based systems, Simple IPC requires pthreads and Unix
|
|
||||||
# domain sockets. So support is only enabled when both are present.
|
|
||||||
#
|
|
||||||
ifdef USE_WIN32_IPC
|
|
||||||
BASIC_CFLAGS += -DSUPPORTS_SIMPLE_IPC
|
|
||||||
LIB_OBJS += compat/simple-ipc/ipc-shared.o
|
|
||||||
LIB_OBJS += compat/simple-ipc/ipc-win32.o
|
|
||||||
else
|
|
||||||
ifndef NO_PTHREADS
|
|
||||||
ifndef NO_UNIX_SOCKETS
|
|
||||||
BASIC_CFLAGS += -DSUPPORTS_SIMPLE_IPC
|
|
||||||
LIB_OBJS += compat/simple-ipc/ipc-shared.o
|
|
||||||
LIB_OBJS += compat/simple-ipc/ipc-unix-socket.o
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef NO_ICONV
|
ifdef NO_ICONV
|
||||||
@ -2005,7 +1965,6 @@ ETC_GITCONFIG_SQ = $(subst ','\'',$(ETC_GITCONFIG))
|
|||||||
ETC_GITATTRIBUTES_SQ = $(subst ','\'',$(ETC_GITATTRIBUTES))
|
ETC_GITATTRIBUTES_SQ = $(subst ','\'',$(ETC_GITATTRIBUTES))
|
||||||
|
|
||||||
DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
|
DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
|
||||||
NO_GETTEXT_SQ = $(subst ','\'',$(NO_GETTEXT))
|
|
||||||
bindir_SQ = $(subst ','\'',$(bindir))
|
bindir_SQ = $(subst ','\'',$(bindir))
|
||||||
bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
|
bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
|
||||||
mandir_SQ = $(subst ','\'',$(mandir))
|
mandir_SQ = $(subst ','\'',$(mandir))
|
||||||
@ -2227,13 +2186,13 @@ $(BUILT_INS): git$X
|
|||||||
|
|
||||||
config-list.h: generate-configlist.sh
|
config-list.h: generate-configlist.sh
|
||||||
|
|
||||||
config-list.h: Documentation/*config.txt Documentation/config/*.txt
|
config-list.h:
|
||||||
$(QUIET_GEN)$(SHELL_PATH) ./generate-configlist.sh \
|
$(QUIET_GEN)$(SHELL_PATH) ./generate-configlist.sh \
|
||||||
>$@+ && mv $@+ $@
|
>$@+ && mv $@+ $@
|
||||||
|
|
||||||
command-list.h: generate-cmdlist.sh command-list.txt
|
command-list.h: generate-cmdlist.sh command-list.txt
|
||||||
|
|
||||||
command-list.h: $(wildcard Documentation/git*.txt)
|
command-list.h: $(wildcard Documentation/git*.txt) Documentation/*config.txt Documentation/config/*.txt
|
||||||
$(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh \
|
$(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh \
|
||||||
$(patsubst %,--exclude-program %,$(EXCLUDED_PROGRAMS)) \
|
$(patsubst %,--exclude-program %,$(EXCLUDED_PROGRAMS)) \
|
||||||
command-list.txt >$@+ && mv $@+ $@
|
command-list.txt >$@+ && mv $@+ $@
|
||||||
@ -2290,13 +2249,10 @@ perl_localedir_SQ = $(localedir_SQ)
|
|||||||
|
|
||||||
ifndef NO_PERL
|
ifndef NO_PERL
|
||||||
PERL_HEADER_TEMPLATE = perl/header_templates/fixed_prefix.template.pl
|
PERL_HEADER_TEMPLATE = perl/header_templates/fixed_prefix.template.pl
|
||||||
PERL_DEFINES =
|
PERL_DEFINES = $(PERL_PATH_SQ):$(PERLLIB_EXTRA_SQ):$(perllibdir_SQ)
|
||||||
PERL_DEFINES += $(PERL_PATH_SQ)
|
|
||||||
PERL_DEFINES += $(PERLLIB_EXTRA_SQ)
|
PERL_DEFINES := $(PERL_PATH_SQ) $(PERLLIB_EXTRA_SQ) $(perllibdir_SQ)
|
||||||
PERL_DEFINES += $(perllibdir_SQ)
|
|
||||||
PERL_DEFINES += $(RUNTIME_PREFIX)
|
PERL_DEFINES += $(RUNTIME_PREFIX)
|
||||||
PERL_DEFINES += $(NO_PERL_CPAN_FALLBACKS)
|
|
||||||
PERL_DEFINES += $(NO_GETTEXT)
|
|
||||||
|
|
||||||
# Support Perl runtime prefix. In this mode, a different header is installed
|
# Support Perl runtime prefix. In this mode, a different header is installed
|
||||||
# into Perl scripts.
|
# into Perl scripts.
|
||||||
@ -2422,30 +2378,16 @@ XDIFF_OBJS += xdiff/xmerge.o
|
|||||||
XDIFF_OBJS += xdiff/xpatience.o
|
XDIFF_OBJS += xdiff/xpatience.o
|
||||||
XDIFF_OBJS += xdiff/xprepare.o
|
XDIFF_OBJS += xdiff/xprepare.o
|
||||||
XDIFF_OBJS += xdiff/xutils.o
|
XDIFF_OBJS += xdiff/xutils.o
|
||||||
.PHONY: xdiff-objs
|
|
||||||
xdiff-objs: $(XDIFF_OBJS)
|
|
||||||
|
|
||||||
TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
|
TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
|
||||||
.PHONY: test-objs
|
OBJECTS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \
|
||||||
test-objs: $(TEST_OBJS)
|
$(XDIFF_OBJS) \
|
||||||
|
$(FUZZ_OBJS) \
|
||||||
GIT_OBJS += $(LIB_OBJS)
|
common-main.o \
|
||||||
GIT_OBJS += $(BUILTIN_OBJS)
|
git.o
|
||||||
GIT_OBJS += common-main.o
|
|
||||||
GIT_OBJS += git.o
|
|
||||||
.PHONY: git-objs
|
|
||||||
git-objs: $(GIT_OBJS)
|
|
||||||
|
|
||||||
OBJECTS += $(GIT_OBJS)
|
|
||||||
OBJECTS += $(PROGRAM_OBJS)
|
|
||||||
OBJECTS += $(TEST_OBJS)
|
|
||||||
OBJECTS += $(XDIFF_OBJS)
|
|
||||||
OBJECTS += $(FUZZ_OBJS)
|
|
||||||
ifndef NO_CURL
|
ifndef NO_CURL
|
||||||
OBJECTS += http.o http-walker.o remote-curl.o
|
OBJECTS += http.o http-walker.o remote-curl.o
|
||||||
endif
|
endif
|
||||||
.PHONY: objects
|
|
||||||
objects: $(OBJECTS)
|
|
||||||
|
|
||||||
dep_files := $(foreach f,$(OBJECTS),$(dir $f).depend/$(notdir $f).d)
|
dep_files := $(foreach f,$(OBJECTS),$(dir $f).depend/$(notdir $f).d)
|
||||||
dep_dirs := $(addsuffix .depend,$(sort $(dir $(OBJECTS))))
|
dep_dirs := $(addsuffix .depend,$(sort $(dir $(OBJECTS))))
|
||||||
@ -2698,10 +2640,9 @@ endif
|
|||||||
NO_PERL_CPAN_FALLBACKS_SQ = $(subst ','\'',$(NO_PERL_CPAN_FALLBACKS))
|
NO_PERL_CPAN_FALLBACKS_SQ = $(subst ','\'',$(NO_PERL_CPAN_FALLBACKS))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
perl/build/lib/%.pm: perl/%.pm GIT-PERL-DEFINES
|
perl/build/lib/%.pm: perl/%.pm
|
||||||
$(QUIET_GEN)mkdir -p $(dir $@) && \
|
$(QUIET_GEN)mkdir -p $(dir $@) && \
|
||||||
sed -e 's|@@LOCALEDIR@@|$(perl_localedir_SQ)|g' \
|
sed -e 's|@@LOCALEDIR@@|$(perl_localedir_SQ)|g' \
|
||||||
-e 's|@@NO_GETTEXT@@|$(NO_GETTEXT_SQ)|g' \
|
|
||||||
-e 's|@@NO_PERL_CPAN_FALLBACKS@@|$(NO_PERL_CPAN_FALLBACKS_SQ)|g' \
|
-e 's|@@NO_PERL_CPAN_FALLBACKS@@|$(NO_PERL_CPAN_FALLBACKS_SQ)|g' \
|
||||||
< $< > $@
|
< $< > $@
|
||||||
|
|
||||||
@ -2728,14 +2669,12 @@ FIND_SOURCE_FILES = ( \
|
|||||||
)
|
)
|
||||||
|
|
||||||
$(ETAGS_TARGET): FORCE
|
$(ETAGS_TARGET): FORCE
|
||||||
$(QUIET_GEN)$(RM) "$(ETAGS_TARGET)+" && \
|
$(RM) $(ETAGS_TARGET)
|
||||||
$(FIND_SOURCE_FILES) | xargs etags -a -o "$(ETAGS_TARGET)+" && \
|
$(FIND_SOURCE_FILES) | xargs etags -a -o $(ETAGS_TARGET)
|
||||||
mv "$(ETAGS_TARGET)+" "$(ETAGS_TARGET)"
|
|
||||||
|
|
||||||
tags: FORCE
|
tags: FORCE
|
||||||
$(QUIET_GEN)$(RM) tags+ && \
|
$(RM) tags
|
||||||
$(FIND_SOURCE_FILES) | xargs ctags -a -o tags+ && \
|
$(FIND_SOURCE_FILES) | xargs ctags -a
|
||||||
mv tags+ tags
|
|
||||||
|
|
||||||
cscope:
|
cscope:
|
||||||
$(RM) cscope*
|
$(RM) cscope*
|
||||||
|
51
SECURITY.md
51
SECURITY.md
@ -1,51 +0,0 @@
|
|||||||
# Security Policy
|
|
||||||
|
|
||||||
## Reporting a vulnerability
|
|
||||||
|
|
||||||
Please send a detailed mail to git-security@googlegroups.com to
|
|
||||||
report vulnerabilities in Git.
|
|
||||||
|
|
||||||
Even when unsure whether the bug in question is an exploitable
|
|
||||||
vulnerability, it is recommended to send the report to
|
|
||||||
git-security@googlegroups.com (and obviously not to discuss the
|
|
||||||
issue anywhere else).
|
|
||||||
|
|
||||||
Vulnerabilities are expected to be discussed _only_ on that
|
|
||||||
list, and not in public, until the official announcement on the
|
|
||||||
Git mailing list on the release date.
|
|
||||||
|
|
||||||
Examples for details to include:
|
|
||||||
|
|
||||||
- Ideally a short description (or a script) to demonstrate an
|
|
||||||
exploit.
|
|
||||||
- The affected platforms and scenarios (the vulnerability might
|
|
||||||
only affect setups with case-sensitive file systems, for
|
|
||||||
example).
|
|
||||||
- The name and affiliation of the security researchers who are
|
|
||||||
involved in the discovery, if any.
|
|
||||||
- Whether the vulnerability has already been disclosed.
|
|
||||||
- How long an embargo would be required to be safe.
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
There are no official "Long Term Support" versions in Git.
|
|
||||||
Instead, the maintenance track (i.e. the versions based on the
|
|
||||||
most recently published feature release, also known as ".0"
|
|
||||||
version) sees occasional updates with bug fixes.
|
|
||||||
|
|
||||||
Fixes to vulnerabilities are made for the maintenance track for
|
|
||||||
the latest feature release and merged up to the in-development
|
|
||||||
branches. The Git project makes no formal guarantee for any
|
|
||||||
older maintenance tracks to receive updates. In practice,
|
|
||||||
though, critical vulnerability fixes are applied not only to the
|
|
||||||
most recent track, but to at least a couple more maintenance
|
|
||||||
tracks.
|
|
||||||
|
|
||||||
This is typically done by making the fix on the oldest and still
|
|
||||||
relevant maintenance track, and merging it upwards to newer and
|
|
||||||
newer maintenance tracks.
|
|
||||||
|
|
||||||
For example, v2.24.1 was released to address a couple of
|
|
||||||
[CVEs](https://cve.mitre.org/), and at the same time v2.14.6,
|
|
||||||
v2.15.4, v2.16.6, v2.17.3, v2.18.2, v2.19.3, v2.20.2, v2.21.1,
|
|
||||||
v2.22.2 and v2.23.1 were released.
|
|
20
advice.c
20
advice.c
@ -2,7 +2,6 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "help.h"
|
#include "help.h"
|
||||||
#include "string-list.h"
|
|
||||||
|
|
||||||
int advice_fetch_show_forced_updates = 1;
|
int advice_fetch_show_forced_updates = 1;
|
||||||
int advice_push_update_rejected = 1;
|
int advice_push_update_rejected = 1;
|
||||||
@ -137,7 +136,6 @@ static struct {
|
|||||||
[ADVICE_STATUS_HINTS] = { "statusHints", 1 },
|
[ADVICE_STATUS_HINTS] = { "statusHints", 1 },
|
||||||
[ADVICE_STATUS_U_OPTION] = { "statusUoption", 1 },
|
[ADVICE_STATUS_U_OPTION] = { "statusUoption", 1 },
|
||||||
[ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE] = { "submoduleAlternateErrorStrategyDie", 1 },
|
[ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE] = { "submoduleAlternateErrorStrategyDie", 1 },
|
||||||
[ADVICE_UPDATE_SPARSE_PATH] = { "updateSparsePath", 1 },
|
|
||||||
[ADVICE_WAITING_FOR_EDITOR] = { "waitingForEditor", 1 },
|
[ADVICE_WAITING_FOR_EDITOR] = { "waitingForEditor", 1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -286,24 +284,6 @@ void NORETURN die_conclude_merge(void)
|
|||||||
die(_("Exiting because of unfinished merge."));
|
die(_("Exiting because of unfinished merge."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void advise_on_updating_sparse_paths(struct string_list *pathspec_list)
|
|
||||||
{
|
|
||||||
struct string_list_item *item;
|
|
||||||
|
|
||||||
if (!pathspec_list->nr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
fprintf(stderr, _("The following pathspecs didn't match any"
|
|
||||||
" eligible path, but they do match index\n"
|
|
||||||
"entries outside the current sparse checkout:\n"));
|
|
||||||
for_each_string_list_item(item, pathspec_list)
|
|
||||||
fprintf(stderr, "%s\n", item->string);
|
|
||||||
|
|
||||||
advise_if_enabled(ADVICE_UPDATE_SPARSE_PATH,
|
|
||||||
_("Disable or modify the sparsity rules if you intend"
|
|
||||||
" to update such entries."));
|
|
||||||
}
|
|
||||||
|
|
||||||
void detach_advice(const char *new_name)
|
void detach_advice(const char *new_name)
|
||||||
{
|
{
|
||||||
const char *fmt =
|
const char *fmt =
|
||||||
|
4
advice.h
4
advice.h
@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
#include "git-compat-util.h"
|
#include "git-compat-util.h"
|
||||||
|
|
||||||
struct string_list;
|
|
||||||
|
|
||||||
extern int advice_fetch_show_forced_updates;
|
extern int advice_fetch_show_forced_updates;
|
||||||
extern int advice_push_update_rejected;
|
extern int advice_push_update_rejected;
|
||||||
extern int advice_push_non_ff_current;
|
extern int advice_push_non_ff_current;
|
||||||
@ -73,7 +71,6 @@ extern int advice_add_empty_pathspec;
|
|||||||
ADVICE_STATUS_HINTS,
|
ADVICE_STATUS_HINTS,
|
||||||
ADVICE_STATUS_U_OPTION,
|
ADVICE_STATUS_U_OPTION,
|
||||||
ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE,
|
ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE,
|
||||||
ADVICE_UPDATE_SPARSE_PATH,
|
|
||||||
ADVICE_WAITING_FOR_EDITOR,
|
ADVICE_WAITING_FOR_EDITOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -95,7 +92,6 @@ void advise_if_enabled(enum advice_type type, const char *advice, ...);
|
|||||||
int error_resolve_conflict(const char *me);
|
int error_resolve_conflict(const char *me);
|
||||||
void NORETURN die_resolve_conflict(const char *me);
|
void NORETURN die_resolve_conflict(const char *me);
|
||||||
void NORETURN die_conclude_merge(void);
|
void NORETURN die_conclude_merge(void);
|
||||||
void advise_on_updating_sparse_paths(struct string_list *pathspec_list);
|
|
||||||
void detach_advice(const char *new_name);
|
void detach_advice(const char *new_name);
|
||||||
|
|
||||||
#endif /* ADVICE_H */
|
#endif /* ADVICE_H */
|
||||||
|
29
apply.c
29
apply.c
@ -21,7 +21,6 @@
|
|||||||
#include "quote.h"
|
#include "quote.h"
|
||||||
#include "rerere.h"
|
#include "rerere.h"
|
||||||
#include "apply.h"
|
#include "apply.h"
|
||||||
#include "entry.h"
|
|
||||||
|
|
||||||
struct gitdiff_data {
|
struct gitdiff_data {
|
||||||
struct strbuf *root;
|
struct strbuf *root;
|
||||||
@ -134,6 +133,8 @@ int check_apply_state(struct apply_state *state, int force_apply)
|
|||||||
|
|
||||||
if (state->apply_with_reject && state->threeway)
|
if (state->apply_with_reject && state->threeway)
|
||||||
return error(_("--reject and --3way cannot be used together."));
|
return error(_("--reject and --3way cannot be used together."));
|
||||||
|
if (state->cached && state->threeway)
|
||||||
|
return error(_("--cached and --3way cannot be used together."));
|
||||||
if (state->threeway) {
|
if (state->threeway) {
|
||||||
if (is_not_gitdir)
|
if (is_not_gitdir)
|
||||||
return error(_("--3way outside a repository"));
|
return error(_("--3way outside a repository"));
|
||||||
@ -3568,10 +3569,10 @@ static int try_threeway(struct apply_state *state,
|
|||||||
write_object_file("", 0, blob_type, &pre_oid);
|
write_object_file("", 0, blob_type, &pre_oid);
|
||||||
else if (get_oid(patch->old_oid_prefix, &pre_oid) ||
|
else if (get_oid(patch->old_oid_prefix, &pre_oid) ||
|
||||||
read_blob_object(&buf, &pre_oid, patch->old_mode))
|
read_blob_object(&buf, &pre_oid, patch->old_mode))
|
||||||
return error(_("repository lacks the necessary blob to perform 3-way merge."));
|
return error(_("repository lacks the necessary blob to fall back on 3-way merge."));
|
||||||
|
|
||||||
if (state->apply_verbosity > verbosity_silent && patch->direct_to_threeway)
|
if (state->apply_verbosity > verbosity_silent)
|
||||||
fprintf(stderr, _("Performing three-way merge...\n"));
|
fprintf(stderr, _("Falling back to three-way merge...\n"));
|
||||||
|
|
||||||
img = strbuf_detach(&buf, &len);
|
img = strbuf_detach(&buf, &len);
|
||||||
prepare_image(&tmp_image, img, len, 1);
|
prepare_image(&tmp_image, img, len, 1);
|
||||||
@ -3603,7 +3604,7 @@ static int try_threeway(struct apply_state *state,
|
|||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
if (state->apply_verbosity > verbosity_silent)
|
if (state->apply_verbosity > verbosity_silent)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
_("Failed to perform three-way merge...\n"));
|
_("Failed to fall back on three-way merge...\n"));
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3636,13 +3637,10 @@ static int apply_data(struct apply_state *state, struct patch *patch,
|
|||||||
if (load_preimage(state, &image, patch, st, ce) < 0)
|
if (load_preimage(state, &image, patch, st, ce) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!state->threeway || try_threeway(state, &image, patch, st, ce) < 0) {
|
if (patch->direct_to_threeway ||
|
||||||
if (state->apply_verbosity > verbosity_silent &&
|
apply_fragments(state, &image, patch) < 0) {
|
||||||
state->threeway && !patch->direct_to_threeway)
|
|
||||||
fprintf(stderr, _("Falling back to direct application...\n"));
|
|
||||||
|
|
||||||
/* Note: with --reject, apply_fragments() returns 0 */
|
/* Note: with --reject, apply_fragments() returns 0 */
|
||||||
if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0)
|
if (!state->threeway || try_threeway(state, &image, patch, st, ce) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
patch->result = image.buf;
|
patch->result = image.buf;
|
||||||
@ -4648,12 +4646,7 @@ static int write_out_results(struct apply_state *state, struct patch *list)
|
|||||||
}
|
}
|
||||||
string_list_clear(&cpath, 0);
|
string_list_clear(&cpath, 0);
|
||||||
|
|
||||||
/*
|
repo_rerere(state->repo, 0);
|
||||||
* rerere relies on the partially merged result being in the working
|
|
||||||
* tree with conflict markers, but that isn't written with --cached.
|
|
||||||
*/
|
|
||||||
if (!state->cached)
|
|
||||||
repo_rerere(state->repo, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return errs;
|
return errs;
|
||||||
@ -5024,7 +5017,7 @@ int apply_parse_options(int argc, const char **argv,
|
|||||||
OPT_BOOL(0, "apply", force_apply,
|
OPT_BOOL(0, "apply", force_apply,
|
||||||
N_("also apply the patch (use with --stat/--summary/--check)")),
|
N_("also apply the patch (use with --stat/--summary/--check)")),
|
||||||
OPT_BOOL('3', "3way", &state->threeway,
|
OPT_BOOL('3', "3way", &state->threeway,
|
||||||
N_( "attempt three-way merge, fall back on normal patch if that fails")),
|
N_( "attempt three-way merge if a patch does not apply")),
|
||||||
OPT_FILENAME(0, "build-fake-ancestor", &state->fake_ancestor,
|
OPT_FILENAME(0, "build-fake-ancestor", &state->fake_ancestor,
|
||||||
N_("build a temporary index based on embedded index information")),
|
N_("build a temporary index based on embedded index information")),
|
||||||
/* Think twice before adding "--nul" synonym to this */
|
/* Think twice before adding "--nul" synonym to this */
|
||||||
|
52
archive.c
52
archive.c
@ -37,10 +37,13 @@ void init_archivers(void)
|
|||||||
|
|
||||||
static void format_subst(const struct commit *commit,
|
static void format_subst(const struct commit *commit,
|
||||||
const char *src, size_t len,
|
const char *src, size_t len,
|
||||||
struct strbuf *buf, struct pretty_print_context *ctx)
|
struct strbuf *buf)
|
||||||
{
|
{
|
||||||
char *to_free = NULL;
|
char *to_free = NULL;
|
||||||
struct strbuf fmt = STRBUF_INIT;
|
struct strbuf fmt = STRBUF_INIT;
|
||||||
|
struct pretty_print_context ctx = {0};
|
||||||
|
ctx.date_mode.type = DATE_NORMAL;
|
||||||
|
ctx.abbrev = DEFAULT_ABBREV;
|
||||||
|
|
||||||
if (src == buf->buf)
|
if (src == buf->buf)
|
||||||
to_free = strbuf_detach(buf, NULL);
|
to_free = strbuf_detach(buf, NULL);
|
||||||
@ -58,7 +61,7 @@ static void format_subst(const struct commit *commit,
|
|||||||
strbuf_add(&fmt, b + 8, c - b - 8);
|
strbuf_add(&fmt, b + 8, c - b - 8);
|
||||||
|
|
||||||
strbuf_add(buf, src, b - src);
|
strbuf_add(buf, src, b - src);
|
||||||
format_commit_message(commit, fmt.buf, buf, ctx);
|
format_commit_message(commit, fmt.buf, buf, &ctx);
|
||||||
len -= c + 1 - src;
|
len -= c + 1 - src;
|
||||||
src = c + 1;
|
src = c + 1;
|
||||||
}
|
}
|
||||||
@ -91,7 +94,7 @@ static void *object_file_to_archive(const struct archiver_args *args,
|
|||||||
strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
|
strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
|
||||||
convert_to_working_tree(args->repo->index, path, buf.buf, buf.len, &buf, &meta);
|
convert_to_working_tree(args->repo->index, path, buf.buf, buf.len, &buf, &meta);
|
||||||
if (commit)
|
if (commit)
|
||||||
format_subst(commit, buf.buf, buf.len, &buf, args->pretty_ctx);
|
format_subst(commit, buf.buf, buf.len, &buf);
|
||||||
buffer = strbuf_detach(&buf, &size);
|
buffer = strbuf_detach(&buf, &size);
|
||||||
*sizep = size;
|
*sizep = size;
|
||||||
}
|
}
|
||||||
@ -104,6 +107,7 @@ struct directory {
|
|||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
int baselen, len;
|
int baselen, len;
|
||||||
unsigned mode;
|
unsigned mode;
|
||||||
|
int stage;
|
||||||
char path[FLEX_ARRAY];
|
char path[FLEX_ARRAY];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -134,7 +138,7 @@ static int check_attr_export_subst(const struct attr_check *check)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int write_archive_entry(const struct object_id *oid, const char *base,
|
static int write_archive_entry(const struct object_id *oid, const char *base,
|
||||||
int baselen, const char *filename, unsigned mode,
|
int baselen, const char *filename, unsigned mode, int stage,
|
||||||
void *context)
|
void *context)
|
||||||
{
|
{
|
||||||
static struct strbuf path = STRBUF_INIT;
|
static struct strbuf path = STRBUF_INIT;
|
||||||
@ -193,7 +197,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
|
|||||||
|
|
||||||
static void queue_directory(const unsigned char *sha1,
|
static void queue_directory(const unsigned char *sha1,
|
||||||
struct strbuf *base, const char *filename,
|
struct strbuf *base, const char *filename,
|
||||||
unsigned mode, struct archiver_context *c)
|
unsigned mode, int stage, struct archiver_context *c)
|
||||||
{
|
{
|
||||||
struct directory *d;
|
struct directory *d;
|
||||||
size_t len = st_add4(base->len, 1, strlen(filename), 1);
|
size_t len = st_add4(base->len, 1, strlen(filename), 1);
|
||||||
@ -201,9 +205,10 @@ static void queue_directory(const unsigned char *sha1,
|
|||||||
d->up = c->bottom;
|
d->up = c->bottom;
|
||||||
d->baselen = base->len;
|
d->baselen = base->len;
|
||||||
d->mode = mode;
|
d->mode = mode;
|
||||||
|
d->stage = stage;
|
||||||
c->bottom = d;
|
c->bottom = d;
|
||||||
d->len = xsnprintf(d->path, len, "%.*s%s/", (int)base->len, base->buf, filename);
|
d->len = xsnprintf(d->path, len, "%.*s%s/", (int)base->len, base->buf, filename);
|
||||||
oidread(&d->oid, sha1);
|
hashcpy(d->oid.hash, sha1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_directory(struct archiver_context *c)
|
static int write_directory(struct archiver_context *c)
|
||||||
@ -219,14 +224,14 @@ static int write_directory(struct archiver_context *c)
|
|||||||
write_directory(c) ||
|
write_directory(c) ||
|
||||||
write_archive_entry(&d->oid, d->path, d->baselen,
|
write_archive_entry(&d->oid, d->path, d->baselen,
|
||||||
d->path + d->baselen, d->mode,
|
d->path + d->baselen, d->mode,
|
||||||
c) != READ_TREE_RECURSIVE;
|
d->stage, c) != READ_TREE_RECURSIVE;
|
||||||
free(d);
|
free(d);
|
||||||
return ret ? -1 : 0;
|
return ret ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int queue_or_write_archive_entry(const struct object_id *oid,
|
static int queue_or_write_archive_entry(const struct object_id *oid,
|
||||||
struct strbuf *base, const char *filename,
|
struct strbuf *base, const char *filename,
|
||||||
unsigned mode, void *context)
|
unsigned mode, int stage, void *context)
|
||||||
{
|
{
|
||||||
struct archiver_context *c = context;
|
struct archiver_context *c = context;
|
||||||
|
|
||||||
@ -251,14 +256,14 @@ static int queue_or_write_archive_entry(const struct object_id *oid,
|
|||||||
if (check_attr_export_ignore(check))
|
if (check_attr_export_ignore(check))
|
||||||
return 0;
|
return 0;
|
||||||
queue_directory(oid->hash, base, filename,
|
queue_directory(oid->hash, base, filename,
|
||||||
mode, c);
|
mode, stage, c);
|
||||||
return READ_TREE_RECURSIVE;
|
return READ_TREE_RECURSIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write_directory(c))
|
if (write_directory(c))
|
||||||
return -1;
|
return -1;
|
||||||
return write_archive_entry(oid, base->buf, base->len, filename, mode,
|
return write_archive_entry(oid, base->buf, base->len, filename, mode,
|
||||||
context);
|
stage, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct extra_file_info {
|
struct extra_file_info {
|
||||||
@ -275,11 +280,9 @@ int write_archive_entries(struct archiver_args *args,
|
|||||||
int err;
|
int err;
|
||||||
struct strbuf path_in_archive = STRBUF_INIT;
|
struct strbuf path_in_archive = STRBUF_INIT;
|
||||||
struct strbuf content = STRBUF_INIT;
|
struct strbuf content = STRBUF_INIT;
|
||||||
struct object_id fake_oid;
|
struct object_id fake_oid = null_oid;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
oidcpy(&fake_oid, null_oid());
|
|
||||||
|
|
||||||
if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
|
if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
|
||||||
size_t len = args->baselen;
|
size_t len = args->baselen;
|
||||||
|
|
||||||
@ -313,10 +316,10 @@ int write_archive_entries(struct archiver_args *args,
|
|||||||
git_attr_set_direction(GIT_ATTR_INDEX);
|
git_attr_set_direction(GIT_ATTR_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = read_tree(args->repo, args->tree,
|
err = read_tree_recursive(args->repo, args->tree, "",
|
||||||
&args->pathspec,
|
0, 0, &args->pathspec,
|
||||||
queue_or_write_archive_entry,
|
queue_or_write_archive_entry,
|
||||||
&context);
|
&context);
|
||||||
if (err == READ_TREE_RECURSIVE)
|
if (err == READ_TREE_RECURSIVE)
|
||||||
err = 0;
|
err = 0;
|
||||||
while (context.bottom) {
|
while (context.bottom) {
|
||||||
@ -375,7 +378,7 @@ struct path_exists_context {
|
|||||||
|
|
||||||
static int reject_entry(const struct object_id *oid, struct strbuf *base,
|
static int reject_entry(const struct object_id *oid, struct strbuf *base,
|
||||||
const char *filename, unsigned mode,
|
const char *filename, unsigned mode,
|
||||||
void *context)
|
int stage, void *context)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct path_exists_context *ctx = context;
|
struct path_exists_context *ctx = context;
|
||||||
@ -402,9 +405,9 @@ static int path_exists(struct archiver_args *args, const char *path)
|
|||||||
ctx.args = args;
|
ctx.args = args;
|
||||||
parse_pathspec(&ctx.pathspec, 0, 0, "", paths);
|
parse_pathspec(&ctx.pathspec, 0, 0, "", paths);
|
||||||
ctx.pathspec.recursive = 1;
|
ctx.pathspec.recursive = 1;
|
||||||
ret = read_tree(args->repo, args->tree,
|
ret = read_tree_recursive(args->repo, args->tree, "",
|
||||||
&ctx.pathspec,
|
0, 0, &ctx.pathspec,
|
||||||
reject_entry, &ctx);
|
reject_entry, &ctx);
|
||||||
clear_pathspec(&ctx.pathspec);
|
clear_pathspec(&ctx.pathspec);
|
||||||
return ret != 0;
|
return ret != 0;
|
||||||
}
|
}
|
||||||
@ -630,19 +633,12 @@ int write_archive(int argc, const char **argv, const char *prefix,
|
|||||||
const char *name_hint, int remote)
|
const char *name_hint, int remote)
|
||||||
{
|
{
|
||||||
const struct archiver *ar = NULL;
|
const struct archiver *ar = NULL;
|
||||||
struct pretty_print_describe_status describe_status = {0};
|
|
||||||
struct pretty_print_context ctx = {0};
|
|
||||||
struct archiver_args args;
|
struct archiver_args args;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
git_config_get_bool("uploadarchive.allowunreachable", &remote_allow_unreachable);
|
git_config_get_bool("uploadarchive.allowunreachable", &remote_allow_unreachable);
|
||||||
git_config(git_default_config, NULL);
|
git_config(git_default_config, NULL);
|
||||||
|
|
||||||
describe_status.max_invocations = 1;
|
|
||||||
ctx.date_mode.type = DATE_NORMAL;
|
|
||||||
ctx.abbrev = DEFAULT_ABBREV;
|
|
||||||
ctx.describe_status = &describe_status;
|
|
||||||
args.pretty_ctx = &ctx;
|
|
||||||
args.repo = repo;
|
args.repo = repo;
|
||||||
args.prefix = prefix;
|
args.prefix = prefix;
|
||||||
string_list_init(&args.extra_files, 1);
|
string_list_init(&args.extra_files, 1);
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include "pathspec.h"
|
#include "pathspec.h"
|
||||||
|
|
||||||
struct repository;
|
struct repository;
|
||||||
struct pretty_print_context;
|
|
||||||
|
|
||||||
struct archiver_args {
|
struct archiver_args {
|
||||||
struct repository *repo;
|
struct repository *repo;
|
||||||
@ -23,7 +22,6 @@ struct archiver_args {
|
|||||||
unsigned int convert : 1;
|
unsigned int convert : 1;
|
||||||
int compression_level;
|
int compression_level;
|
||||||
struct string_list extra_files;
|
struct string_list extra_files;
|
||||||
struct pretty_print_context *pretty_ctx;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* main api */
|
/* main api */
|
||||||
|
161
attr.c
161
attr.c
@ -28,7 +28,7 @@ static const char git_attr__unknown[] = "(builtin)unknown";
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct git_attr {
|
struct git_attr {
|
||||||
int attr_nr; /* unique attribute number */
|
unsigned int attr_nr; /* unique attribute number */
|
||||||
char name[FLEX_ARRAY]; /* attribute name */
|
char name[FLEX_ARRAY]; /* attribute name */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -210,7 +210,7 @@ static void report_invalid_attr(const char *name, size_t len,
|
|||||||
* dictionary. If no entry is found, create a new attribute and store it in
|
* dictionary. If no entry is found, create a new attribute and store it in
|
||||||
* the dictionary.
|
* the dictionary.
|
||||||
*/
|
*/
|
||||||
static const struct git_attr *git_attr_internal(const char *name, int namelen)
|
static const struct git_attr *git_attr_internal(const char *name, size_t namelen)
|
||||||
{
|
{
|
||||||
struct git_attr *a;
|
struct git_attr *a;
|
||||||
|
|
||||||
@ -226,8 +226,8 @@ static const struct git_attr *git_attr_internal(const char *name, int namelen)
|
|||||||
a->attr_nr = hashmap_get_size(&g_attr_hashmap.map);
|
a->attr_nr = hashmap_get_size(&g_attr_hashmap.map);
|
||||||
|
|
||||||
attr_hashmap_add(&g_attr_hashmap, a->name, namelen, a);
|
attr_hashmap_add(&g_attr_hashmap, a->name, namelen, a);
|
||||||
assert(a->attr_nr ==
|
if (a->attr_nr != hashmap_get_size(&g_attr_hashmap.map) - 1)
|
||||||
(hashmap_get_size(&g_attr_hashmap.map) - 1));
|
die(_("unable to add additional attribute"));
|
||||||
}
|
}
|
||||||
|
|
||||||
hashmap_unlock(&g_attr_hashmap);
|
hashmap_unlock(&g_attr_hashmap);
|
||||||
@ -272,16 +272,12 @@ struct match_attr {
|
|||||||
const struct git_attr *attr;
|
const struct git_attr *attr;
|
||||||
} u;
|
} u;
|
||||||
char is_macro;
|
char is_macro;
|
||||||
unsigned num_attr;
|
size_t num_attr;
|
||||||
struct attr_state state[FLEX_ARRAY];
|
struct attr_state state[FLEX_ARRAY];
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char blank[] = " \t\r\n";
|
static const char blank[] = " \t\r\n";
|
||||||
|
|
||||||
/* Flags usable in read_attr() and parse_attr_line() family of functions. */
|
|
||||||
#define READ_ATTR_MACRO_OK (1<<0)
|
|
||||||
#define READ_ATTR_NOFOLLOW (1<<1)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse a whitespace-delimited attribute state (i.e., "attr",
|
* Parse a whitespace-delimited attribute state (i.e., "attr",
|
||||||
* "-attr", "!attr", or "attr=value") from the string starting at src.
|
* "-attr", "!attr", or "attr=value") from the string starting at src.
|
||||||
@ -293,7 +289,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
|
|||||||
struct attr_state *e)
|
struct attr_state *e)
|
||||||
{
|
{
|
||||||
const char *ep, *equals;
|
const char *ep, *equals;
|
||||||
int len;
|
size_t len;
|
||||||
|
|
||||||
ep = cp + strcspn(cp, blank);
|
ep = cp + strcspn(cp, blank);
|
||||||
equals = strchr(cp, '=');
|
equals = strchr(cp, '=');
|
||||||
@ -335,10 +331,9 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct match_attr *parse_attr_line(const char *line, const char *src,
|
static struct match_attr *parse_attr_line(const char *line, const char *src,
|
||||||
int lineno, unsigned flags)
|
int lineno, int macro_ok)
|
||||||
{
|
{
|
||||||
int namelen;
|
size_t namelen, num_attr, i;
|
||||||
int num_attr, i;
|
|
||||||
const char *cp, *name, *states;
|
const char *cp, *name, *states;
|
||||||
struct match_attr *res = NULL;
|
struct match_attr *res = NULL;
|
||||||
int is_macro;
|
int is_macro;
|
||||||
@ -349,6 +344,11 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
|
|||||||
return NULL;
|
return NULL;
|
||||||
name = cp;
|
name = cp;
|
||||||
|
|
||||||
|
if (strlen(line) >= ATTR_MAX_LINE_LENGTH) {
|
||||||
|
warning(_("ignoring overly long attributes line %d"), lineno);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (*cp == '"' && !unquote_c_style(&pattern, name, &states)) {
|
if (*cp == '"' && !unquote_c_style(&pattern, name, &states)) {
|
||||||
name = pattern.buf;
|
name = pattern.buf;
|
||||||
namelen = pattern.len;
|
namelen = pattern.len;
|
||||||
@ -359,7 +359,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
|
|||||||
|
|
||||||
if (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen &&
|
if (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen &&
|
||||||
starts_with(name, ATTRIBUTE_MACRO_PREFIX)) {
|
starts_with(name, ATTRIBUTE_MACRO_PREFIX)) {
|
||||||
if (!(flags & READ_ATTR_MACRO_OK)) {
|
if (!macro_ok) {
|
||||||
fprintf_ln(stderr, _("%s not allowed: %s:%d"),
|
fprintf_ln(stderr, _("%s not allowed: %s:%d"),
|
||||||
name, src, lineno);
|
name, src, lineno);
|
||||||
goto fail_return;
|
goto fail_return;
|
||||||
@ -385,10 +385,9 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
|
|||||||
goto fail_return;
|
goto fail_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = xcalloc(1,
|
res = xcalloc(1, st_add3(sizeof(*res),
|
||||||
sizeof(*res) +
|
st_mult(sizeof(struct attr_state), num_attr),
|
||||||
sizeof(struct attr_state) * num_attr +
|
is_macro ? 0 : namelen + 1));
|
||||||
(is_macro ? 0 : namelen + 1));
|
|
||||||
if (is_macro) {
|
if (is_macro) {
|
||||||
res->u.attr = git_attr_internal(name, namelen);
|
res->u.attr = git_attr_internal(name, namelen);
|
||||||
} else {
|
} else {
|
||||||
@ -451,11 +450,12 @@ struct attr_stack {
|
|||||||
|
|
||||||
static void attr_stack_free(struct attr_stack *e)
|
static void attr_stack_free(struct attr_stack *e)
|
||||||
{
|
{
|
||||||
int i;
|
unsigned i;
|
||||||
free(e->origin);
|
free(e->origin);
|
||||||
for (i = 0; i < e->num_matches; i++) {
|
for (i = 0; i < e->num_matches; i++) {
|
||||||
struct match_attr *a = e->attrs[i];
|
struct match_attr *a = e->attrs[i];
|
||||||
int j;
|
size_t j;
|
||||||
|
|
||||||
for (j = 0; j < a->num_attr; j++) {
|
for (j = 0; j < a->num_attr; j++) {
|
||||||
const char *setto = a->state[j].setto;
|
const char *setto = a->state[j].setto;
|
||||||
if (setto == ATTR__TRUE ||
|
if (setto == ATTR__TRUE ||
|
||||||
@ -657,15 +657,15 @@ static void handle_attr_line(struct attr_stack *res,
|
|||||||
const char *line,
|
const char *line,
|
||||||
const char *src,
|
const char *src,
|
||||||
int lineno,
|
int lineno,
|
||||||
unsigned flags)
|
int macro_ok)
|
||||||
{
|
{
|
||||||
struct match_attr *a;
|
struct match_attr *a;
|
||||||
|
|
||||||
a = parse_attr_line(line, src, lineno, flags);
|
a = parse_attr_line(line, src, lineno, macro_ok);
|
||||||
if (!a)
|
if (!a)
|
||||||
return;
|
return;
|
||||||
ALLOC_GROW(res->attrs, res->num_matches + 1, res->alloc);
|
ALLOC_GROW_BY(res->attrs, res->num_matches, 1, res->alloc);
|
||||||
res->attrs[res->num_matches++] = a;
|
res->attrs[res->num_matches - 1] = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct attr_stack *read_attr_from_array(const char **list)
|
static struct attr_stack *read_attr_from_array(const char **list)
|
||||||
@ -676,8 +676,7 @@ static struct attr_stack *read_attr_from_array(const char **list)
|
|||||||
|
|
||||||
CALLOC_ARRAY(res, 1);
|
CALLOC_ARRAY(res, 1);
|
||||||
while ((line = *(list++)) != NULL)
|
while ((line = *(list++)) != NULL)
|
||||||
handle_attr_line(res, line, "[builtin]", ++lineno,
|
handle_attr_line(res, line, "[builtin]", ++lineno, 1);
|
||||||
READ_ATTR_MACRO_OK);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -703,50 +702,61 @@ void git_attr_set_direction(enum git_attr_direction new_direction)
|
|||||||
direction = new_direction;
|
direction = new_direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct attr_stack *read_attr_from_file(const char *path, unsigned flags)
|
static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
|
||||||
{
|
{
|
||||||
int fd;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
FILE *fp;
|
FILE *fp = fopen_or_warn(path, "r");
|
||||||
struct attr_stack *res;
|
struct attr_stack *res;
|
||||||
char buf[2048];
|
|
||||||
int lineno = 0;
|
int lineno = 0;
|
||||||
|
int fd;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
if (flags & READ_ATTR_NOFOLLOW)
|
if (!fp)
|
||||||
fd = open_nofollow(path, O_RDONLY);
|
return NULL;
|
||||||
else
|
|
||||||
fd = open(path, O_RDONLY);
|
|
||||||
|
|
||||||
if (fd < 0) {
|
fd = fileno(fp);
|
||||||
warn_on_fopen_errors(path);
|
if (fstat(fd, &st)) {
|
||||||
|
warning_errno(_("cannot fstat gitattributes file '%s'"), path);
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (st.st_size >= ATTR_MAX_FILE_SIZE) {
|
||||||
|
warning(_("ignoring overly large gitattributes file '%s'"), path);
|
||||||
|
fclose(fp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
fp = xfdopen(fd, "r");
|
|
||||||
|
|
||||||
CALLOC_ARRAY(res, 1);
|
CALLOC_ARRAY(res, 1);
|
||||||
while (fgets(buf, sizeof(buf), fp)) {
|
while (strbuf_getline(&buf, fp) != EOF) {
|
||||||
char *bufp = buf;
|
if (!lineno && starts_with(buf.buf, utf8_bom))
|
||||||
if (!lineno)
|
strbuf_remove(&buf, 0, strlen(utf8_bom));
|
||||||
skip_utf8_bom(&bufp, strlen(bufp));
|
handle_attr_line(res, buf.buf, path, ++lineno, macro_ok);
|
||||||
handle_attr_line(res, bufp, path, ++lineno, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
strbuf_release(&buf);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct attr_stack *read_attr_from_index(struct index_state *istate,
|
static struct attr_stack *read_attr_from_index(const struct index_state *istate,
|
||||||
const char *path,
|
const char *path,
|
||||||
unsigned flags)
|
int macro_ok)
|
||||||
{
|
{
|
||||||
struct attr_stack *res;
|
struct attr_stack *res;
|
||||||
char *buf, *sp;
|
char *buf, *sp;
|
||||||
int lineno = 0;
|
int lineno = 0;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
if (!istate)
|
if (!istate)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
buf = read_blob_data_from_index(istate, path, NULL);
|
buf = read_blob_data_from_index(istate, path, &size);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if (size >= ATTR_MAX_FILE_SIZE) {
|
||||||
|
warning(_("ignoring overly large gitattributes blob '%s'"), path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
CALLOC_ARRAY(res, 1);
|
CALLOC_ARRAY(res, 1);
|
||||||
for (sp = buf; *sp; ) {
|
for (sp = buf; *sp; ) {
|
||||||
@ -756,27 +766,27 @@ static struct attr_stack *read_attr_from_index(struct index_state *istate,
|
|||||||
ep = strchrnul(sp, '\n');
|
ep = strchrnul(sp, '\n');
|
||||||
more = (*ep == '\n');
|
more = (*ep == '\n');
|
||||||
*ep = '\0';
|
*ep = '\0';
|
||||||
handle_attr_line(res, sp, path, ++lineno, flags);
|
handle_attr_line(res, sp, path, ++lineno, macro_ok);
|
||||||
sp = ep + more;
|
sp = ep + more;
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct attr_stack *read_attr(struct index_state *istate,
|
static struct attr_stack *read_attr(const struct index_state *istate,
|
||||||
const char *path, unsigned flags)
|
const char *path, int macro_ok)
|
||||||
{
|
{
|
||||||
struct attr_stack *res = NULL;
|
struct attr_stack *res = NULL;
|
||||||
|
|
||||||
if (direction == GIT_ATTR_INDEX) {
|
if (direction == GIT_ATTR_INDEX) {
|
||||||
res = read_attr_from_index(istate, path, flags);
|
res = read_attr_from_index(istate, path, macro_ok);
|
||||||
} else if (!is_bare_repository()) {
|
} else if (!is_bare_repository()) {
|
||||||
if (direction == GIT_ATTR_CHECKOUT) {
|
if (direction == GIT_ATTR_CHECKOUT) {
|
||||||
res = read_attr_from_index(istate, path, flags);
|
res = read_attr_from_index(istate, path, macro_ok);
|
||||||
if (!res)
|
if (!res)
|
||||||
res = read_attr_from_file(path, flags);
|
res = read_attr_from_file(path, macro_ok);
|
||||||
} else if (direction == GIT_ATTR_CHECKIN) {
|
} else if (direction == GIT_ATTR_CHECKIN) {
|
||||||
res = read_attr_from_file(path, flags);
|
res = read_attr_from_file(path, macro_ok);
|
||||||
if (!res)
|
if (!res)
|
||||||
/*
|
/*
|
||||||
* There is no checked out .gitattributes file
|
* There is no checked out .gitattributes file
|
||||||
@ -784,7 +794,7 @@ static struct attr_stack *read_attr(struct index_state *istate,
|
|||||||
* We allow operation in a sparsely checked out
|
* We allow operation in a sparsely checked out
|
||||||
* work tree, so read from it.
|
* work tree, so read from it.
|
||||||
*/
|
*/
|
||||||
res = read_attr_from_index(istate, path, flags);
|
res = read_attr_from_index(istate, path, macro_ok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -855,11 +865,10 @@ static void push_stack(struct attr_stack **attr_stack_p,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bootstrap_attr_stack(struct index_state *istate,
|
static void bootstrap_attr_stack(const struct index_state *istate,
|
||||||
struct attr_stack **stack)
|
struct attr_stack **stack)
|
||||||
{
|
{
|
||||||
struct attr_stack *e;
|
struct attr_stack *e;
|
||||||
unsigned flags = READ_ATTR_MACRO_OK;
|
|
||||||
|
|
||||||
if (*stack)
|
if (*stack)
|
||||||
return;
|
return;
|
||||||
@ -870,23 +879,23 @@ static void bootstrap_attr_stack(struct index_state *istate,
|
|||||||
|
|
||||||
/* system-wide frame */
|
/* system-wide frame */
|
||||||
if (git_attr_system()) {
|
if (git_attr_system()) {
|
||||||
e = read_attr_from_file(git_etc_gitattributes(), flags);
|
e = read_attr_from_file(git_etc_gitattributes(), 1);
|
||||||
push_stack(stack, e, NULL, 0);
|
push_stack(stack, e, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* home directory */
|
/* home directory */
|
||||||
if (get_home_gitattributes()) {
|
if (get_home_gitattributes()) {
|
||||||
e = read_attr_from_file(get_home_gitattributes(), flags);
|
e = read_attr_from_file(get_home_gitattributes(), 1);
|
||||||
push_stack(stack, e, NULL, 0);
|
push_stack(stack, e, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* root directory */
|
/* root directory */
|
||||||
e = read_attr(istate, GITATTRIBUTES_FILE, flags | READ_ATTR_NOFOLLOW);
|
e = read_attr(istate, GITATTRIBUTES_FILE, 1);
|
||||||
push_stack(stack, e, xstrdup(""), 0);
|
push_stack(stack, e, xstrdup(""), 0);
|
||||||
|
|
||||||
/* info frame */
|
/* info frame */
|
||||||
if (startup_info->have_repository)
|
if (startup_info->have_repository)
|
||||||
e = read_attr_from_file(git_path_info_attributes(), flags);
|
e = read_attr_from_file(git_path_info_attributes(), 1);
|
||||||
else
|
else
|
||||||
e = NULL;
|
e = NULL;
|
||||||
if (!e)
|
if (!e)
|
||||||
@ -894,7 +903,7 @@ static void bootstrap_attr_stack(struct index_state *istate,
|
|||||||
push_stack(stack, e, NULL, 0);
|
push_stack(stack, e, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prepare_attr_stack(struct index_state *istate,
|
static void prepare_attr_stack(const struct index_state *istate,
|
||||||
const char *path, int dirlen,
|
const char *path, int dirlen,
|
||||||
struct attr_stack **stack)
|
struct attr_stack **stack)
|
||||||
{
|
{
|
||||||
@ -972,7 +981,7 @@ static void prepare_attr_stack(struct index_state *istate,
|
|||||||
strbuf_add(&pathbuf, path + pathbuf.len, (len - pathbuf.len));
|
strbuf_add(&pathbuf, path + pathbuf.len, (len - pathbuf.len));
|
||||||
strbuf_addf(&pathbuf, "/%s", GITATTRIBUTES_FILE);
|
strbuf_addf(&pathbuf, "/%s", GITATTRIBUTES_FILE);
|
||||||
|
|
||||||
next = read_attr(istate, pathbuf.buf, READ_ATTR_NOFOLLOW);
|
next = read_attr(istate, pathbuf.buf, 0);
|
||||||
|
|
||||||
/* reset the pathbuf to not include "/.gitattributes" */
|
/* reset the pathbuf to not include "/.gitattributes" */
|
||||||
strbuf_setlen(&pathbuf, len);
|
strbuf_setlen(&pathbuf, len);
|
||||||
@ -1017,12 +1026,12 @@ static int macroexpand_one(struct all_attrs_item *all_attrs, int nr, int rem);
|
|||||||
static int fill_one(const char *what, struct all_attrs_item *all_attrs,
|
static int fill_one(const char *what, struct all_attrs_item *all_attrs,
|
||||||
const struct match_attr *a, int rem)
|
const struct match_attr *a, int rem)
|
||||||
{
|
{
|
||||||
int i;
|
size_t i;
|
||||||
|
|
||||||
for (i = a->num_attr - 1; rem > 0 && i >= 0; i--) {
|
for (i = a->num_attr; rem > 0 && i > 0; i--) {
|
||||||
const struct git_attr *attr = a->state[i].attr;
|
const struct git_attr *attr = a->state[i - 1].attr;
|
||||||
const char **n = &(all_attrs[attr->attr_nr].value);
|
const char **n = &(all_attrs[attr->attr_nr].value);
|
||||||
const char *v = a->state[i].setto;
|
const char *v = a->state[i - 1].setto;
|
||||||
|
|
||||||
if (*n == ATTR__UNKNOWN) {
|
if (*n == ATTR__UNKNOWN) {
|
||||||
debug_set(what,
|
debug_set(what,
|
||||||
@ -1041,11 +1050,11 @@ static int fill(const char *path, int pathlen, int basename_offset,
|
|||||||
struct all_attrs_item *all_attrs, int rem)
|
struct all_attrs_item *all_attrs, int rem)
|
||||||
{
|
{
|
||||||
for (; rem > 0 && stack; stack = stack->prev) {
|
for (; rem > 0 && stack; stack = stack->prev) {
|
||||||
int i;
|
unsigned i;
|
||||||
const char *base = stack->origin ? stack->origin : "";
|
const char *base = stack->origin ? stack->origin : "";
|
||||||
|
|
||||||
for (i = stack->num_matches - 1; 0 < rem && 0 <= i; i--) {
|
for (i = stack->num_matches; 0 < rem && 0 < i; i--) {
|
||||||
const struct match_attr *a = stack->attrs[i];
|
const struct match_attr *a = stack->attrs[i - 1];
|
||||||
if (a->is_macro)
|
if (a->is_macro)
|
||||||
continue;
|
continue;
|
||||||
if (path_matches(path, pathlen, basename_offset,
|
if (path_matches(path, pathlen, basename_offset,
|
||||||
@ -1076,11 +1085,11 @@ static void determine_macros(struct all_attrs_item *all_attrs,
|
|||||||
const struct attr_stack *stack)
|
const struct attr_stack *stack)
|
||||||
{
|
{
|
||||||
for (; stack; stack = stack->prev) {
|
for (; stack; stack = stack->prev) {
|
||||||
int i;
|
unsigned i;
|
||||||
for (i = stack->num_matches - 1; i >= 0; i--) {
|
for (i = stack->num_matches; i > 0; i--) {
|
||||||
const struct match_attr *ma = stack->attrs[i];
|
const struct match_attr *ma = stack->attrs[i - 1];
|
||||||
if (ma->is_macro) {
|
if (ma->is_macro) {
|
||||||
int n = ma->u.attr->attr_nr;
|
unsigned int n = ma->u.attr->attr_nr;
|
||||||
if (!all_attrs[n].macro) {
|
if (!all_attrs[n].macro) {
|
||||||
all_attrs[n].macro = ma;
|
all_attrs[n].macro = ma;
|
||||||
}
|
}
|
||||||
@ -1094,7 +1103,7 @@ static void determine_macros(struct all_attrs_item *all_attrs,
|
|||||||
* If check->check_nr is non-zero, only attributes in check[] are collected.
|
* If check->check_nr is non-zero, only attributes in check[] are collected.
|
||||||
* Otherwise all attributes are collected.
|
* Otherwise all attributes are collected.
|
||||||
*/
|
*/
|
||||||
static void collect_some_attrs(struct index_state *istate,
|
static void collect_some_attrs(const struct index_state *istate,
|
||||||
const char *path,
|
const char *path,
|
||||||
struct attr_check *check)
|
struct attr_check *check)
|
||||||
{
|
{
|
||||||
@ -1123,7 +1132,7 @@ static void collect_some_attrs(struct index_state *istate,
|
|||||||
fill(path, pathlen, basename_offset, check->stack, check->all_attrs, rem);
|
fill(path, pathlen, basename_offset, check->stack, check->all_attrs, rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_check_attr(struct index_state *istate,
|
void git_check_attr(const struct index_state *istate,
|
||||||
const char *path,
|
const char *path,
|
||||||
struct attr_check *check)
|
struct attr_check *check)
|
||||||
{
|
{
|
||||||
@ -1132,7 +1141,7 @@ void git_check_attr(struct index_state *istate,
|
|||||||
collect_some_attrs(istate, path, check);
|
collect_some_attrs(istate, path, check);
|
||||||
|
|
||||||
for (i = 0; i < check->nr; i++) {
|
for (i = 0; i < check->nr; i++) {
|
||||||
size_t n = check->items[i].attr->attr_nr;
|
unsigned int n = check->items[i].attr->attr_nr;
|
||||||
const char *value = check->all_attrs[n].value;
|
const char *value = check->all_attrs[n].value;
|
||||||
if (value == ATTR__UNKNOWN)
|
if (value == ATTR__UNKNOWN)
|
||||||
value = ATTR__UNSET;
|
value = ATTR__UNSET;
|
||||||
@ -1140,7 +1149,7 @@ void git_check_attr(struct index_state *istate,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_all_attrs(struct index_state *istate,
|
void git_all_attrs(const struct index_state *istate,
|
||||||
const char *path, struct attr_check *check)
|
const char *path, struct attr_check *check)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
16
attr.h
16
attr.h
@ -107,6 +107,18 @@
|
|||||||
* - Free the `attr_check` struct by calling `attr_check_free()`.
|
* - Free the `attr_check` struct by calling `attr_check_free()`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum line length for a gitattributes file. If the line exceeds this
|
||||||
|
* length we will ignore it.
|
||||||
|
*/
|
||||||
|
#define ATTR_MAX_LINE_LENGTH 2048
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum size of the giattributes file. If the file exceeds this size we
|
||||||
|
* will ignore it.
|
||||||
|
*/
|
||||||
|
#define ATTR_MAX_FILE_SIZE (100 * 1024 * 1024)
|
||||||
|
|
||||||
struct index_state;
|
struct index_state;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -190,14 +202,14 @@ void attr_check_free(struct attr_check *check);
|
|||||||
*/
|
*/
|
||||||
const char *git_attr_name(const struct git_attr *);
|
const char *git_attr_name(const struct git_attr *);
|
||||||
|
|
||||||
void git_check_attr(struct index_state *istate,
|
void git_check_attr(const struct index_state *istate,
|
||||||
const char *path, struct attr_check *check);
|
const char *path, struct attr_check *check);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Retrieve all attributes that apply to the specified path.
|
* Retrieve all attributes that apply to the specified path.
|
||||||
* check holds the attributes and their values.
|
* check holds the attributes and their values.
|
||||||
*/
|
*/
|
||||||
void git_all_attrs(struct index_state *istate,
|
void git_all_attrs(const struct index_state *istate,
|
||||||
const char *path, struct attr_check *check);
|
const char *path, struct attr_check *check);
|
||||||
|
|
||||||
enum git_attr_direction {
|
enum git_attr_direction {
|
||||||
|
2
blame.c
2
blame.c
@ -242,7 +242,7 @@ static struct commit *fake_working_tree_commit(struct repository *r,
|
|||||||
switch (st.st_mode & S_IFMT) {
|
switch (st.st_mode & S_IFMT) {
|
||||||
case S_IFREG:
|
case S_IFREG:
|
||||||
if (opt->flags.allow_textconv &&
|
if (opt->flags.allow_textconv &&
|
||||||
textconv_object(r, read_from, mode, null_oid(), 0, &buf_ptr, &buf_len))
|
textconv_object(r, read_from, mode, &null_oid, 0, &buf_ptr, &buf_len))
|
||||||
strbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1);
|
strbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1);
|
||||||
else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
|
else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
|
||||||
die_errno("cannot open or read '%s'", read_from);
|
die_errno("cannot open or read '%s'", read_from);
|
||||||
|
1
bloom.c
1
bloom.c
@ -283,7 +283,6 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
|
|||||||
struct bloom_key key;
|
struct bloom_key key;
|
||||||
fill_bloom_key(e->path, strlen(e->path), &key, settings);
|
fill_bloom_key(e->path, strlen(e->path), &key, settings);
|
||||||
add_key_to_filter(&key, filter, settings);
|
add_key_to_filter(&key, filter, settings);
|
||||||
clear_bloom_key(&key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
5
branch.c
5
branch.c
@ -294,7 +294,7 @@ void create_branch(struct repository *r,
|
|||||||
if (explicit_tracking)
|
if (explicit_tracking)
|
||||||
die(_(upstream_not_branch), start_name);
|
die(_(upstream_not_branch), start_name);
|
||||||
else
|
else
|
||||||
FREE_AND_NULL(real_ref);
|
real_ref = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -322,7 +322,7 @@ void create_branch(struct repository *r,
|
|||||||
transaction = ref_transaction_begin(&err);
|
transaction = ref_transaction_begin(&err);
|
||||||
if (!transaction ||
|
if (!transaction ||
|
||||||
ref_transaction_update(transaction, ref.buf,
|
ref_transaction_update(transaction, ref.buf,
|
||||||
&oid, forcing ? NULL : null_oid(),
|
&oid, forcing ? NULL : &null_oid,
|
||||||
0, msg, &err) ||
|
0, msg, &err) ||
|
||||||
ref_transaction_commit(transaction, &err))
|
ref_transaction_commit(transaction, &err))
|
||||||
die("%s", err.buf);
|
die("%s", err.buf);
|
||||||
@ -344,7 +344,6 @@ void remove_merge_branch_state(struct repository *r)
|
|||||||
unlink(git_path_merge_rr(r));
|
unlink(git_path_merge_rr(r));
|
||||||
unlink(git_path_merge_msg(r));
|
unlink(git_path_merge_msg(r));
|
||||||
unlink(git_path_merge_mode(r));
|
unlink(git_path_merge_mode(r));
|
||||||
unlink(git_path_auto_merge(r));
|
|
||||||
save_autostash(git_path_merge_autostash(r));
|
save_autostash(git_path_merge_autostash(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,6 @@ int cmd_bugreport(int argc, const char **argv, const char *prefix);
|
|||||||
int cmd_bundle(int argc, const char **argv, const char *prefix);
|
int cmd_bundle(int argc, const char **argv, const char *prefix);
|
||||||
int cmd_cat_file(int argc, const char **argv, const char *prefix);
|
int cmd_cat_file(int argc, const char **argv, const char *prefix);
|
||||||
int cmd_checkout(int argc, const char **argv, const char *prefix);
|
int cmd_checkout(int argc, const char **argv, const char *prefix);
|
||||||
int cmd_checkout__worker(int argc, const char **argv, const char *prefix);
|
|
||||||
int cmd_checkout_index(int argc, const char **argv, const char *prefix);
|
int cmd_checkout_index(int argc, const char **argv, const char *prefix);
|
||||||
int cmd_check_attr(int argc, const char **argv, const char *prefix);
|
int cmd_check_attr(int argc, const char **argv, const char *prefix);
|
||||||
int cmd_check_ignore(int argc, const char **argv, const char *prefix);
|
int cmd_check_ignore(int argc, const char **argv, const char *prefix);
|
||||||
|
@ -46,9 +46,6 @@ static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only)
|
|||||||
struct cache_entry *ce = active_cache[i];
|
struct cache_entry *ce = active_cache[i];
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (ce_skip_worktree(ce))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
|
if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -144,13 +141,9 @@ static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
|
|||||||
{
|
{
|
||||||
int i, retval = 0;
|
int i, retval = 0;
|
||||||
|
|
||||||
/* TODO: audit for interaction with sparse-index. */
|
|
||||||
ensure_full_index(&the_index);
|
|
||||||
for (i = 0; i < active_nr; i++) {
|
for (i = 0; i < active_nr; i++) {
|
||||||
struct cache_entry *ce = active_cache[i];
|
struct cache_entry *ce = active_cache[i];
|
||||||
|
|
||||||
if (ce_skip_worktree(ce))
|
|
||||||
continue;
|
|
||||||
if (ce_stage(ce))
|
if (ce_stage(ce))
|
||||||
continue; /* do not touch unmerged paths */
|
continue; /* do not touch unmerged paths */
|
||||||
if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
|
if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
|
||||||
@ -179,44 +172,24 @@ static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec,
|
|||||||
*dst++ = entry;
|
*dst++ = entry;
|
||||||
}
|
}
|
||||||
dir->nr = dst - dir->entries;
|
dir->nr = dst - dir->entries;
|
||||||
add_pathspec_matches_against_index(pathspec, &the_index, seen,
|
add_pathspec_matches_against_index(pathspec, &the_index, seen);
|
||||||
PS_IGNORE_SKIP_WORKTREE);
|
|
||||||
return seen;
|
return seen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int refresh(int verbose, const struct pathspec *pathspec)
|
static void refresh(int verbose, const struct pathspec *pathspec)
|
||||||
{
|
{
|
||||||
char *seen;
|
char *seen;
|
||||||
int i, ret = 0;
|
int i;
|
||||||
char *skip_worktree_seen = NULL;
|
|
||||||
struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP;
|
|
||||||
int flags = REFRESH_IGNORE_SKIP_WORKTREE |
|
|
||||||
(verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET);
|
|
||||||
|
|
||||||
seen = xcalloc(pathspec->nr, 1);
|
seen = xcalloc(pathspec->nr, 1);
|
||||||
refresh_index(&the_index, flags, pathspec, seen,
|
refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
|
||||||
_("Unstaged changes after refreshing the index:"));
|
pathspec, seen, _("Unstaged changes after refreshing the index:"));
|
||||||
for (i = 0; i < pathspec->nr; i++) {
|
for (i = 0; i < pathspec->nr; i++) {
|
||||||
if (!seen[i]) {
|
if (!seen[i])
|
||||||
if (matches_skip_worktree(pathspec, i, &skip_worktree_seen)) {
|
die(_("pathspec '%s' did not match any files"),
|
||||||
string_list_append(&only_match_skip_worktree,
|
pathspec->items[i].match);
|
||||||
pathspec->items[i].original);
|
|
||||||
} else {
|
|
||||||
die(_("pathspec '%s' did not match any files"),
|
|
||||||
pathspec->items[i].original);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (only_match_skip_worktree.nr) {
|
|
||||||
advise_on_updating_sparse_paths(&only_match_skip_worktree);
|
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(seen);
|
free(seen);
|
||||||
free(skip_worktree_seen);
|
|
||||||
string_list_clear(&only_match_skip_worktree, 0);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_add_interactive(const char *revision, const char *patch_mode,
|
int run_add_interactive(const char *revision, const char *patch_mode,
|
||||||
@ -484,8 +457,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
|||||||
if (patch_interactive)
|
if (patch_interactive)
|
||||||
add_interactive = 1;
|
add_interactive = 1;
|
||||||
if (add_interactive) {
|
if (add_interactive) {
|
||||||
if (show_only)
|
|
||||||
die(_("--dry-run is incompatible with --interactive/--patch"));
|
|
||||||
if (pathspec_from_file)
|
if (pathspec_from_file)
|
||||||
die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
|
die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
|
||||||
exit(interactive_add(argv + 1, prefix, patch_interactive));
|
exit(interactive_add(argv + 1, prefix, patch_interactive));
|
||||||
@ -594,18 +565,15 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (refresh_only) {
|
if (refresh_only) {
|
||||||
exit_status |= refresh(verbose, &pathspec);
|
refresh(verbose, &pathspec);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pathspec.nr) {
|
if (pathspec.nr) {
|
||||||
int i;
|
int i;
|
||||||
char *skip_worktree_seen = NULL;
|
|
||||||
struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP;
|
|
||||||
|
|
||||||
if (!seen)
|
if (!seen)
|
||||||
seen = find_pathspecs_matching_against_index(&pathspec,
|
seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
|
||||||
&the_index, PS_IGNORE_SKIP_WORKTREE);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* file_exists() assumes exact match
|
* file_exists() assumes exact match
|
||||||
@ -619,24 +587,12 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
for (i = 0; i < pathspec.nr; i++) {
|
for (i = 0; i < pathspec.nr; i++) {
|
||||||
const char *path = pathspec.items[i].match;
|
const char *path = pathspec.items[i].match;
|
||||||
|
|
||||||
if (pathspec.items[i].magic & PATHSPEC_EXCLUDE)
|
if (pathspec.items[i].magic & PATHSPEC_EXCLUDE)
|
||||||
continue;
|
continue;
|
||||||
if (seen[i])
|
if (!seen[i] && path[0] &&
|
||||||
continue;
|
((pathspec.items[i].magic &
|
||||||
|
(PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
|
||||||
if (matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) {
|
!file_exists(path))) {
|
||||||
string_list_append(&only_match_skip_worktree,
|
|
||||||
pathspec.items[i].original);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't complain at 'git add .' on empty repo */
|
|
||||||
if (!path[0])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((pathspec.items[i].magic & (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
|
|
||||||
!file_exists(path)) {
|
|
||||||
if (ignore_missing) {
|
if (ignore_missing) {
|
||||||
int dtype = DT_UNKNOWN;
|
int dtype = DT_UNKNOWN;
|
||||||
if (is_excluded(&dir, &the_index, path, &dtype))
|
if (is_excluded(&dir, &the_index, path, &dtype))
|
||||||
@ -647,16 +603,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
|||||||
pathspec.items[i].original);
|
pathspec.items[i].original);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (only_match_skip_worktree.nr) {
|
|
||||||
advise_on_updating_sparse_paths(&only_match_skip_worktree);
|
|
||||||
exit_status = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(seen);
|
free(seen);
|
||||||
free(skip_worktree_seen);
|
|
||||||
string_list_clear(&only_match_skip_worktree, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
plug_bulk_checkin();
|
plug_bulk_checkin();
|
||||||
|
51
builtin/am.c
51
builtin/am.c
@ -116,7 +116,6 @@ struct am_state {
|
|||||||
int keep; /* enum keep_type */
|
int keep; /* enum keep_type */
|
||||||
int message_id;
|
int message_id;
|
||||||
int scissors; /* enum scissors_type */
|
int scissors; /* enum scissors_type */
|
||||||
int quoted_cr; /* enum quoted_cr_action */
|
|
||||||
struct strvec git_apply_opts;
|
struct strvec git_apply_opts;
|
||||||
const char *resolvemsg;
|
const char *resolvemsg;
|
||||||
int committer_date_is_author_date;
|
int committer_date_is_author_date;
|
||||||
@ -146,7 +145,6 @@ static void am_state_init(struct am_state *state)
|
|||||||
git_config_get_bool("am.messageid", &state->message_id);
|
git_config_get_bool("am.messageid", &state->message_id);
|
||||||
|
|
||||||
state->scissors = SCISSORS_UNSET;
|
state->scissors = SCISSORS_UNSET;
|
||||||
state->quoted_cr = quoted_cr_unset;
|
|
||||||
|
|
||||||
strvec_init(&state->git_apply_opts);
|
strvec_init(&state->git_apply_opts);
|
||||||
|
|
||||||
@ -167,16 +165,6 @@ static void am_state_release(struct am_state *state)
|
|||||||
strvec_clear(&state->git_apply_opts);
|
strvec_clear(&state->git_apply_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int am_option_parse_quoted_cr(const struct option *opt,
|
|
||||||
const char *arg, int unset)
|
|
||||||
{
|
|
||||||
BUG_ON_OPT_NEG(unset);
|
|
||||||
|
|
||||||
if (mailinfo_parse_quoted_cr_action(arg, opt->value) != 0)
|
|
||||||
return error(_("bad action '%s' for '%s'"), arg, "--quoted-cr");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns path relative to the am_state directory.
|
* Returns path relative to the am_state directory.
|
||||||
*/
|
*/
|
||||||
@ -409,12 +397,6 @@ static void am_load(struct am_state *state)
|
|||||||
else
|
else
|
||||||
state->scissors = SCISSORS_UNSET;
|
state->scissors = SCISSORS_UNSET;
|
||||||
|
|
||||||
read_state_file(&sb, state, "quoted-cr", 1);
|
|
||||||
if (!*sb.buf)
|
|
||||||
state->quoted_cr = quoted_cr_unset;
|
|
||||||
else if (mailinfo_parse_quoted_cr_action(sb.buf, &state->quoted_cr) != 0)
|
|
||||||
die(_("could not parse %s"), am_path(state, "quoted-cr"));
|
|
||||||
|
|
||||||
read_state_file(&sb, state, "apply-opt", 1);
|
read_state_file(&sb, state, "apply-opt", 1);
|
||||||
strvec_clear(&state->git_apply_opts);
|
strvec_clear(&state->git_apply_opts);
|
||||||
if (sq_dequote_to_strvec(sb.buf, &state->git_apply_opts) < 0)
|
if (sq_dequote_to_strvec(sb.buf, &state->git_apply_opts) < 0)
|
||||||
@ -1020,24 +1002,6 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
|
|||||||
}
|
}
|
||||||
write_state_text(state, "scissors", str);
|
write_state_text(state, "scissors", str);
|
||||||
|
|
||||||
switch (state->quoted_cr) {
|
|
||||||
case quoted_cr_unset:
|
|
||||||
str = "";
|
|
||||||
break;
|
|
||||||
case quoted_cr_nowarn:
|
|
||||||
str = "nowarn";
|
|
||||||
break;
|
|
||||||
case quoted_cr_warn:
|
|
||||||
str = "warn";
|
|
||||||
break;
|
|
||||||
case quoted_cr_strip:
|
|
||||||
str = "strip";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BUG("invalid value for state->quoted_cr");
|
|
||||||
}
|
|
||||||
write_state_text(state, "quoted-cr", str);
|
|
||||||
|
|
||||||
sq_quote_argv(&sb, state->git_apply_opts.v);
|
sq_quote_argv(&sb, state->git_apply_opts.v);
|
||||||
write_state_text(state, "apply-opt", sb.buf);
|
write_state_text(state, "apply-opt", sb.buf);
|
||||||
|
|
||||||
@ -1198,18 +1162,6 @@ static int parse_mail(struct am_state *state, const char *mail)
|
|||||||
BUG("invalid value for state->scissors");
|
BUG("invalid value for state->scissors");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (state->quoted_cr) {
|
|
||||||
case quoted_cr_unset:
|
|
||||||
break;
|
|
||||||
case quoted_cr_nowarn:
|
|
||||||
case quoted_cr_warn:
|
|
||||||
case quoted_cr_strip:
|
|
||||||
mi.quoted_cr = state->quoted_cr;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BUG("invalid value for state->quoted_cr");
|
|
||||||
}
|
|
||||||
|
|
||||||
mi.input = xfopen(mail, "r");
|
mi.input = xfopen(mail, "r");
|
||||||
mi.output = xfopen(am_path(state, "info"), "w");
|
mi.output = xfopen(am_path(state, "info"), "w");
|
||||||
if (mailinfo(&mi, am_path(state, "msg"), am_path(state, "patch")))
|
if (mailinfo(&mi, am_path(state, "msg"), am_path(state, "patch")))
|
||||||
@ -2290,9 +2242,6 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
|||||||
0, PARSE_OPT_NONEG),
|
0, PARSE_OPT_NONEG),
|
||||||
OPT_BOOL('c', "scissors", &state.scissors,
|
OPT_BOOL('c', "scissors", &state.scissors,
|
||||||
N_("strip everything before a scissors line")),
|
N_("strip everything before a scissors line")),
|
||||||
OPT_CALLBACK_F(0, "quoted-cr", &state.quoted_cr, N_("action"),
|
|
||||||
N_("pass it through git-mailinfo"),
|
|
||||||
PARSE_OPT_NONEG, am_option_parse_quoted_cr),
|
|
||||||
OPT_PASSTHRU_ARGV(0, "whitespace", &state.git_apply_opts, N_("action"),
|
OPT_PASSTHRU_ARGV(0, "whitespace", &state.git_apply_opts, N_("action"),
|
||||||
N_("pass it through git-apply"),
|
N_("pass it through git-apply"),
|
||||||
0),
|
0),
|
||||||
|
@ -1126,7 +1126,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
|
|||||||
break;
|
break;
|
||||||
case BISECT_SKIP:
|
case BISECT_SKIP:
|
||||||
set_terms(&terms, "bad", "good");
|
set_terms(&terms, "bad", "good");
|
||||||
get_terms(&terms);
|
|
||||||
res = bisect_skip(&terms, argv, argc);
|
res = bisect_skip(&terms, argv, argc);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -411,8 +411,6 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct ref_array array;
|
struct ref_array array;
|
||||||
struct strbuf out = STRBUF_INIT;
|
|
||||||
struct strbuf err = STRBUF_INIT;
|
|
||||||
int maxwidth = 0;
|
int maxwidth = 0;
|
||||||
const char *remote_prefix = "";
|
const char *remote_prefix = "";
|
||||||
char *to_free = NULL;
|
char *to_free = NULL;
|
||||||
@ -442,8 +440,8 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
|
|||||||
ref_array_sort(sorting, &array);
|
ref_array_sort(sorting, &array);
|
||||||
|
|
||||||
for (i = 0; i < array.nr; i++) {
|
for (i = 0; i < array.nr; i++) {
|
||||||
strbuf_reset(&err);
|
struct strbuf out = STRBUF_INIT;
|
||||||
strbuf_reset(&out);
|
struct strbuf err = STRBUF_INIT;
|
||||||
if (format_ref_array_item(array.items[i], format, &out, &err))
|
if (format_ref_array_item(array.items[i], format, &out, &err))
|
||||||
die("%s", err.buf);
|
die("%s", err.buf);
|
||||||
if (column_active(colopts)) {
|
if (column_active(colopts)) {
|
||||||
@ -454,10 +452,10 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
|
|||||||
fwrite(out.buf, 1, out.len, stdout);
|
fwrite(out.buf, 1, out.len, stdout);
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
strbuf_release(&err);
|
||||||
|
strbuf_release(&out);
|
||||||
}
|
}
|
||||||
|
|
||||||
strbuf_release(&err);
|
|
||||||
strbuf_release(&out);
|
|
||||||
ref_array_clear(&array);
|
ref_array_clear(&array);
|
||||||
free(to_free);
|
free(to_free);
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,6 @@ int cmd_bugreport(int argc, const char **argv, const char *prefix)
|
|||||||
char *option_output = NULL;
|
char *option_output = NULL;
|
||||||
char *option_suffix = "%Y-%m-%d-%H%M";
|
char *option_suffix = "%Y-%m-%d-%H%M";
|
||||||
const char *user_relative_path = NULL;
|
const char *user_relative_path = NULL;
|
||||||
char *prefixed_filename;
|
|
||||||
|
|
||||||
const struct option bugreport_options[] = {
|
const struct option bugreport_options[] = {
|
||||||
OPT_STRING('o', "output-directory", &option_output, N_("path"),
|
OPT_STRING('o', "output-directory", &option_output, N_("path"),
|
||||||
@ -143,9 +142,9 @@ int cmd_bugreport(int argc, const char **argv, const char *prefix)
|
|||||||
bugreport_usage, 0);
|
bugreport_usage, 0);
|
||||||
|
|
||||||
/* Prepare the path to put the result */
|
/* Prepare the path to put the result */
|
||||||
prefixed_filename = prefix_filename(prefix,
|
strbuf_addstr(&report_path,
|
||||||
option_output ? option_output : "");
|
prefix_filename(prefix,
|
||||||
strbuf_addstr(&report_path, prefixed_filename);
|
option_output ? option_output : ""));
|
||||||
strbuf_complete(&report_path, '/');
|
strbuf_complete(&report_path, '/');
|
||||||
|
|
||||||
strbuf_addstr(&report_path, "git-bugreport-");
|
strbuf_addstr(&report_path, "git-bugreport-");
|
||||||
@ -190,7 +189,6 @@ int cmd_bugreport(int argc, const char **argv, const char *prefix)
|
|||||||
fprintf(stderr, _("Created new report at '%s'.\n"),
|
fprintf(stderr, _("Created new report at '%s'.\n"),
|
||||||
user_relative_path);
|
user_relative_path);
|
||||||
|
|
||||||
free(prefixed_filename);
|
|
||||||
UNLEAK(buffer);
|
UNLEAK(buffer);
|
||||||
UNLEAK(report_path);
|
UNLEAK(report_path);
|
||||||
return !!launch_editor(report_path.buf, NULL, NULL);
|
return !!launch_editor(report_path.buf, NULL, NULL);
|
||||||
|
@ -100,8 +100,7 @@ static int check_ignore(struct dir_struct *dir,
|
|||||||
* should not be ignored, in order to be consistent with
|
* should not be ignored, in order to be consistent with
|
||||||
* 'git status', 'git add' etc.
|
* 'git status', 'git add' etc.
|
||||||
*/
|
*/
|
||||||
seen = find_pathspecs_matching_against_index(&pathspec, &the_index,
|
seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
|
||||||
PS_HEED_SKIP_WORKTREE);
|
|
||||||
for (i = 0; i < pathspec.nr; i++) {
|
for (i = 0; i < pathspec.nr; i++) {
|
||||||
full_path = pathspec.items[i].match;
|
full_path = pathspec.items[i].match;
|
||||||
pattern = NULL;
|
pattern = NULL;
|
||||||
@ -119,7 +118,6 @@ static int check_ignore(struct dir_struct *dir,
|
|||||||
num_ignored++;
|
num_ignored++;
|
||||||
}
|
}
|
||||||
free(seen);
|
free(seen);
|
||||||
clear_pathspec(&pathspec);
|
|
||||||
|
|
||||||
return num_ignored;
|
return num_ignored;
|
||||||
}
|
}
|
||||||
|
@ -1,145 +0,0 @@
|
|||||||
#include "builtin.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "entry.h"
|
|
||||||
#include "parallel-checkout.h"
|
|
||||||
#include "parse-options.h"
|
|
||||||
#include "pkt-line.h"
|
|
||||||
|
|
||||||
static void packet_to_pc_item(const char *buffer, int len,
|
|
||||||
struct parallel_checkout_item *pc_item)
|
|
||||||
{
|
|
||||||
const struct pc_item_fixed_portion *fixed_portion;
|
|
||||||
const char *variant;
|
|
||||||
char *encoding;
|
|
||||||
|
|
||||||
if (len < sizeof(struct pc_item_fixed_portion))
|
|
||||||
BUG("checkout worker received too short item (got %dB, exp %dB)",
|
|
||||||
len, (int)sizeof(struct pc_item_fixed_portion));
|
|
||||||
|
|
||||||
fixed_portion = (struct pc_item_fixed_portion *)buffer;
|
|
||||||
|
|
||||||
if (len - sizeof(struct pc_item_fixed_portion) !=
|
|
||||||
fixed_portion->name_len + fixed_portion->working_tree_encoding_len)
|
|
||||||
BUG("checkout worker received corrupted item");
|
|
||||||
|
|
||||||
variant = buffer + sizeof(struct pc_item_fixed_portion);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note: the main process uses zero length to communicate that the
|
|
||||||
* encoding is NULL. There is no use case that requires sending an
|
|
||||||
* actual empty string, since convert_attrs() never sets
|
|
||||||
* ca.working_tree_enconding to "".
|
|
||||||
*/
|
|
||||||
if (fixed_portion->working_tree_encoding_len) {
|
|
||||||
encoding = xmemdupz(variant,
|
|
||||||
fixed_portion->working_tree_encoding_len);
|
|
||||||
variant += fixed_portion->working_tree_encoding_len;
|
|
||||||
} else {
|
|
||||||
encoding = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(pc_item, 0, sizeof(*pc_item));
|
|
||||||
pc_item->ce = make_empty_transient_cache_entry(fixed_portion->name_len, NULL);
|
|
||||||
pc_item->ce->ce_namelen = fixed_portion->name_len;
|
|
||||||
pc_item->ce->ce_mode = fixed_portion->ce_mode;
|
|
||||||
memcpy(pc_item->ce->name, variant, pc_item->ce->ce_namelen);
|
|
||||||
oidcpy(&pc_item->ce->oid, &fixed_portion->oid);
|
|
||||||
|
|
||||||
pc_item->id = fixed_portion->id;
|
|
||||||
pc_item->ca.crlf_action = fixed_portion->crlf_action;
|
|
||||||
pc_item->ca.ident = fixed_portion->ident;
|
|
||||||
pc_item->ca.working_tree_encoding = encoding;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void report_result(struct parallel_checkout_item *pc_item)
|
|
||||||
{
|
|
||||||
struct pc_item_result res;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
res.id = pc_item->id;
|
|
||||||
res.status = pc_item->status;
|
|
||||||
|
|
||||||
if (pc_item->status == PC_ITEM_WRITTEN) {
|
|
||||||
res.st = pc_item->st;
|
|
||||||
size = sizeof(res);
|
|
||||||
} else {
|
|
||||||
size = PC_ITEM_RESULT_BASE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
packet_write(1, (const char *)&res, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free the worker-side malloced data, but not pc_item itself. */
|
|
||||||
static void release_pc_item_data(struct parallel_checkout_item *pc_item)
|
|
||||||
{
|
|
||||||
free((char *)pc_item->ca.working_tree_encoding);
|
|
||||||
discard_cache_entry(pc_item->ce);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void worker_loop(struct checkout *state)
|
|
||||||
{
|
|
||||||
struct parallel_checkout_item *items = NULL;
|
|
||||||
size_t i, nr = 0, alloc = 0;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
int len = packet_read(0, NULL, NULL, packet_buffer,
|
|
||||||
sizeof(packet_buffer), 0);
|
|
||||||
|
|
||||||
if (len < 0)
|
|
||||||
BUG("packet_read() returned negative value");
|
|
||||||
else if (!len)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ALLOC_GROW(items, nr + 1, alloc);
|
|
||||||
packet_to_pc_item(packet_buffer, len, &items[nr++]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nr; i++) {
|
|
||||||
struct parallel_checkout_item *pc_item = &items[i];
|
|
||||||
write_pc_item(pc_item, state);
|
|
||||||
report_result(pc_item);
|
|
||||||
release_pc_item_data(pc_item);
|
|
||||||
}
|
|
||||||
|
|
||||||
packet_flush(1);
|
|
||||||
|
|
||||||
free(items);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char * const checkout_worker_usage[] = {
|
|
||||||
N_("git checkout--worker [<options>]"),
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
int cmd_checkout__worker(int argc, const char **argv, const char *prefix)
|
|
||||||
{
|
|
||||||
struct checkout state = CHECKOUT_INIT;
|
|
||||||
struct option checkout_worker_options[] = {
|
|
||||||
OPT_STRING(0, "prefix", &state.base_dir, N_("string"),
|
|
||||||
N_("when creating files, prepend <string>")),
|
|
||||||
OPT_END()
|
|
||||||
};
|
|
||||||
|
|
||||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
|
||||||
usage_with_options(checkout_worker_usage,
|
|
||||||
checkout_worker_options);
|
|
||||||
|
|
||||||
git_config(git_default_config, NULL);
|
|
||||||
argc = parse_options(argc, argv, prefix, checkout_worker_options,
|
|
||||||
checkout_worker_usage, 0);
|
|
||||||
if (argc > 0)
|
|
||||||
usage_with_options(checkout_worker_usage, checkout_worker_options);
|
|
||||||
|
|
||||||
if (state.base_dir)
|
|
||||||
state.base_dir_len = strlen(state.base_dir);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Setting this on a worker won't actually update the index. We just
|
|
||||||
* need to tell the checkout machinery to lstat() the written entries,
|
|
||||||
* so that we can send this data back to the main process.
|
|
||||||
*/
|
|
||||||
state.refresh_cache = 1;
|
|
||||||
|
|
||||||
worker_loop(&state);
|
|
||||||
return 0;
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user