Mark t1301 permission test to depend on POSIXPERM
This prepares the topic for inclusion to master.
This commit is contained in:
commit
7d5a1806e8
@ -129,3 +129,6 @@ For C programs:
|
||||
used in the git core command set (unless your command is clearly
|
||||
separate from it, such as an importer to convert random-scm-X
|
||||
repositories to git).
|
||||
|
||||
- When we pass <string, length> pair to functions, we should try to
|
||||
pass them in that order.
|
||||
|
@ -41,7 +41,8 @@ man7dir=$(mandir)/man7
|
||||
|
||||
ASCIIDOC=asciidoc
|
||||
ASCIIDOC_EXTRA =
|
||||
MANPAGE_XSL = callouts.xsl
|
||||
MANPAGE_XSL = manpage-normal.xsl
|
||||
XMLTO_EXTRA =
|
||||
INSTALL?=install
|
||||
RM ?= rm -f
|
||||
DOC_REF = origin/man
|
||||
@ -59,13 +60,52 @@ endif
|
||||
-include ../config.mak.autogen
|
||||
-include ../config.mak
|
||||
|
||||
#
|
||||
# For asciidoc ...
|
||||
# -7.1.2, no extra settings are needed.
|
||||
# 8.0-, set ASCIIDOC8.
|
||||
#
|
||||
|
||||
#
|
||||
# For docbook-xsl ...
|
||||
# -1.68.1, set ASCIIDOC_NO_ROFF? (based on changelog from 1.73.0)
|
||||
# 1.69.0, no extra settings are needed?
|
||||
# 1.69.1-1.71.0, set DOCBOOK_SUPPRESS_SP?
|
||||
# 1.71.1, no extra settings are needed?
|
||||
# 1.72.0, set DOCBOOK_XSL_172.
|
||||
# 1.73.0-, set ASCIIDOC_NO_ROFF
|
||||
#
|
||||
|
||||
#
|
||||
# If you had been using DOCBOOK_XSL_172 in an attempt to get rid
|
||||
# of 'the ".ft C" problem' in your generated manpages, and you
|
||||
# instead ended up with weird characters around callouts, try
|
||||
# using ASCIIDOC_NO_ROFF instead (it works fine with ASCIIDOC8).
|
||||
#
|
||||
|
||||
ifdef ASCIIDOC8
|
||||
ASCIIDOC_EXTRA += -a asciidoc7compatible
|
||||
endif
|
||||
ifdef DOCBOOK_XSL_172
|
||||
ASCIIDOC_EXTRA += -a docbook-xsl-172
|
||||
ASCIIDOC_EXTRA += -a git-asciidoc-no-roff
|
||||
MANPAGE_XSL = manpage-1.72.xsl
|
||||
else
|
||||
ifdef ASCIIDOC_NO_ROFF
|
||||
# docbook-xsl after 1.72 needs the regular XSL, but will not
|
||||
# pass-thru raw roff codes from asciidoc.conf, so turn them off.
|
||||
ASCIIDOC_EXTRA += -a git-asciidoc-no-roff
|
||||
endif
|
||||
endif
|
||||
ifdef MAN_BOLD_LITERAL
|
||||
XMLTO_EXTRA += -m manpage-bold-literal.xsl
|
||||
endif
|
||||
ifdef DOCBOOK_SUPPRESS_SP
|
||||
XMLTO_EXTRA += -m manpage-suppress-sp.xsl
|
||||
endif
|
||||
|
||||
SHELL_PATH ?= $(SHELL)
|
||||
# Shell quote;
|
||||
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
|
||||
|
||||
#
|
||||
# Please note that there is a minor bug in asciidoc.
|
||||
@ -76,6 +116,32 @@ endif
|
||||
# yourself - yes, all 6 characters of it!
|
||||
#
|
||||
|
||||
QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
|
||||
QUIET_SUBDIR1 =
|
||||
|
||||
ifneq ($(findstring $(MAKEFLAGS),w),w)
|
||||
PRINT_DIR = --no-print-directory
|
||||
else # "make -w"
|
||||
NO_SUBDIR = :
|
||||
endif
|
||||
|
||||
ifneq ($(findstring $(MAKEFLAGS),s),s)
|
||||
ifndef V
|
||||
QUIET_ASCIIDOC = @echo ' ' ASCIIDOC $@;
|
||||
QUIET_XMLTO = @echo ' ' XMLTO $@;
|
||||
QUIET_DB2TEXI = @echo ' ' DB2TEXI $@;
|
||||
QUIET_MAKEINFO = @echo ' ' MAKEINFO $@;
|
||||
QUIET_DBLATEX = @echo ' ' DBLATEX $@;
|
||||
QUIET_XSLTPROC = @echo ' ' XSLTPROC $@;
|
||||
QUIET_GEN = @echo ' ' GEN $@;
|
||||
QUIET_STDERR = 2> /dev/null
|
||||
QUIET_SUBDIR0 = +@subdir=
|
||||
QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
|
||||
$(MAKE) $(PRINT_DIR) -C $$subdir
|
||||
export V
|
||||
endif
|
||||
endif
|
||||
|
||||
all: html man
|
||||
|
||||
html: $(DOC_HTML)
|
||||
@ -116,10 +182,10 @@ install-pdf: pdf
|
||||
$(INSTALL) -m 644 user-manual.pdf $(DESTDIR)$(pdfdir)
|
||||
|
||||
install-html: html
|
||||
sh ./install-webdoc.sh $(DESTDIR)$(htmldir)
|
||||
'$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
|
||||
|
||||
../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
||||
$(MAKE) -C ../ GIT-VERSION-FILE
|
||||
$(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) GIT-VERSION-FILE
|
||||
|
||||
-include ../GIT-VERSION-FILE
|
||||
|
||||
@ -127,8 +193,8 @@ install-html: html
|
||||
# Determine "include::" file references in asciidoc files.
|
||||
#
|
||||
doc.dep : $(wildcard *.txt) build-docdep.perl
|
||||
$(RM) $@+ $@
|
||||
$(PERL_PATH) ./build-docdep.perl >$@+
|
||||
$(QUIET_GEN)$(RM) $@+ $@ && \
|
||||
$(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \
|
||||
mv $@+ $@
|
||||
|
||||
-include doc.dep
|
||||
@ -146,102 +212,105 @@ cmds_txt = cmds-ancillaryinterrogators.txt \
|
||||
$(cmds_txt): cmd-list.made
|
||||
|
||||
cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
|
||||
$(RM) $@
|
||||
$(PERL_PATH) ./cmd-list.perl ../command-list.txt
|
||||
$(QUIET_GEN)$(RM) $@ && \
|
||||
$(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \
|
||||
date >$@
|
||||
|
||||
clean:
|
||||
$(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7
|
||||
$(RM) *.texi *.texi+ git.info gitman.info
|
||||
$(RM) *.texi *.texi+ *.texi++ git.info gitman.info
|
||||
$(RM) howto-index.txt howto/*.html doc.dep
|
||||
$(RM) technical/api-*.html technical/api-index.txt
|
||||
$(RM) $(cmds_txt) *.made
|
||||
|
||||
$(MAN_HTML): %.html : %.txt
|
||||
$(RM) $@+ $@
|
||||
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
|
||||
$(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \
|
||||
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $<
|
||||
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \
|
||||
mv $@+ $@
|
||||
|
||||
%.1 %.5 %.7 : %.xml
|
||||
$(RM) $@
|
||||
xmlto -m $(MANPAGE_XSL) man $<
|
||||
$(QUIET_XMLTO)$(RM) $@ && \
|
||||
xmlto -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
|
||||
|
||||
%.xml : %.txt
|
||||
$(RM) $@+ $@
|
||||
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
|
||||
$(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
|
||||
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $<
|
||||
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \
|
||||
mv $@+ $@
|
||||
|
||||
user-manual.xml: user-manual.txt user-manual.conf
|
||||
$(ASCIIDOC) -b docbook -d book $<
|
||||
$(QUIET_ASCIIDOC)$(ASCIIDOC) -b docbook -d book $<
|
||||
|
||||
technical/api-index.txt: technical/api-index-skel.txt \
|
||||
technical/api-index.sh $(patsubst %,%.txt,$(API_DOCS))
|
||||
cd technical && sh ./api-index.sh
|
||||
$(QUIET_GEN)cd technical && '$(SHELL_PATH_SQ)' ./api-index.sh
|
||||
|
||||
$(patsubst %,%.html,$(API_DOCS) technical/api-index): %.html : %.txt
|
||||
$(ASCIIDOC) -b xhtml11 -f asciidoc.conf \
|
||||
$(QUIET_ASCIIDOC)$(ASCIIDOC) -b xhtml11 -f asciidoc.conf \
|
||||
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) $*.txt
|
||||
|
||||
XSLT = docbook.xsl
|
||||
XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css
|
||||
|
||||
user-manual.html: user-manual.xml
|
||||
xsltproc $(XSLTOPTS) -o $@ $(XSLT) $<
|
||||
$(QUIET_XSLTPROC)xsltproc $(XSLTOPTS) -o $@ $(XSLT) $<
|
||||
|
||||
git.info: user-manual.texi
|
||||
$(MAKEINFO) --no-split -o $@ user-manual.texi
|
||||
$(QUIET_MAKEINFO)$(MAKEINFO) --no-split -o $@ user-manual.texi
|
||||
|
||||
user-manual.texi: user-manual.xml
|
||||
$(RM) $@+ $@
|
||||
$(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout | \
|
||||
$(PERL_PATH) fix-texi.perl >$@+
|
||||
$(QUIET_DB2TEXI)$(RM) $@+ $@ && \
|
||||
$(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout >$@++ && \
|
||||
$(PERL_PATH) fix-texi.perl <$@++ >$@+ && \
|
||||
rm $@++ && \
|
||||
mv $@+ $@
|
||||
|
||||
user-manual.pdf: user-manual.xml
|
||||
$(RM) $@+ $@
|
||||
$(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $<
|
||||
$(QUIET_DBLATEX)$(RM) $@+ $@ && \
|
||||
$(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $< && \
|
||||
mv $@+ $@
|
||||
|
||||
gitman.texi: $(MAN_XML) cat-texi.perl
|
||||
$(RM) $@+ $@
|
||||
$(QUIET_DB2TEXI)$(RM) $@+ $@ && \
|
||||
($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \
|
||||
--to-stdout $(xml);)) | $(PERL_PATH) cat-texi.perl $@ >$@+
|
||||
--to-stdout $(xml) &&) true) > $@++ && \
|
||||
$(PERL_PATH) cat-texi.perl $@ <$@++ >$@+ && \
|
||||
rm $@++ && \
|
||||
mv $@+ $@
|
||||
|
||||
gitman.info: gitman.texi
|
||||
$(MAKEINFO) --no-split --no-validate $*.texi
|
||||
$(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $*.texi
|
||||
|
||||
$(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml
|
||||
$(RM) $@+ $@
|
||||
$(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+
|
||||
$(QUIET_DB2TEXI)$(RM) $@+ $@ && \
|
||||
$(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+ && \
|
||||
mv $@+ $@
|
||||
|
||||
howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
|
||||
$(RM) $@+ $@
|
||||
sh ./howto-index.sh $(wildcard howto/*.txt) >$@+
|
||||
$(QUIET_GEN)$(RM) $@+ $@ && \
|
||||
'$(SHELL_PATH_SQ)' ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \
|
||||
mv $@+ $@
|
||||
|
||||
$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
|
||||
$(ASCIIDOC) -b xhtml11 $*.txt
|
||||
$(QUIET_ASCIIDOC)$(ASCIIDOC) -b xhtml11 $*.txt
|
||||
|
||||
WEBDOC_DEST = /pub/software/scm/git/docs
|
||||
|
||||
$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
|
||||
$(RM) $@+ $@
|
||||
sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+
|
||||
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
|
||||
sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+ && \
|
||||
mv $@+ $@
|
||||
|
||||
install-webdoc : html
|
||||
sh ./install-webdoc.sh $(WEBDOC_DEST)
|
||||
'$(SHELL_PATH_SQ)' ./install-webdoc.sh $(WEBDOC_DEST)
|
||||
|
||||
quick-install: quick-install-man
|
||||
|
||||
quick-install-man:
|
||||
sh ./install-doc-quick.sh $(DOC_REF) $(DESTDIR)$(mandir)
|
||||
'$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(DOC_REF) $(DESTDIR)$(mandir)
|
||||
|
||||
quick-install-html:
|
||||
sh ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir)
|
||||
'$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir)
|
||||
|
||||
.PHONY: .FORCE-GIT-VERSION-FILE
|
||||
|
@ -7,9 +7,15 @@ Fixes since v1.6.2.1
|
||||
* A longstanding confusing description of what --pickaxe option of
|
||||
git-diff does has been clarified in the documentation.
|
||||
|
||||
* "git-blame -S" did not quite work near the commits that were given
|
||||
on the command line correctly.
|
||||
|
||||
* "git diff --pickaxe-regexp" did not count overlapping matches
|
||||
correctly.
|
||||
|
||||
* "git diff" did not feed files in work-tree representation to external
|
||||
diff and textconv.
|
||||
|
||||
* "git-fetch" in a repository that was not cloned from anywhere said
|
||||
it cannot find 'origin', which was hard to understand for new people.
|
||||
|
||||
@ -27,9 +33,13 @@ Fixes since v1.6.2.1
|
||||
* 'git-submodule add' did not tolerate extra slashes and ./ in the path it
|
||||
accepted from the command line; it now is more lenient.
|
||||
|
||||
* git-svn misbehaved when the project contained a path that began with
|
||||
two dashes.
|
||||
|
||||
---
|
||||
exec >/var/tmp/1
|
||||
O=v1.6.2.1-23-g67c176f
|
||||
echo O=$(git describe maint)
|
||||
git shortlog --no-merges $O..maint
|
||||
* import-zips script (in contrib) did not compute the common directory
|
||||
prefix correctly.
|
||||
|
||||
* miscompilation of negated enum constants by old gcc (2.9) affected the
|
||||
codepaths to spawn subprocesses.
|
||||
|
||||
Many small documentation updates are included as well.
|
||||
|
22
Documentation/RelNotes-1.6.2.3.txt
Normal file
22
Documentation/RelNotes-1.6.2.3.txt
Normal file
@ -0,0 +1,22 @@
|
||||
GIT v1.6.2.3 Release Notes
|
||||
==========================
|
||||
|
||||
Fixes since v1.6.2.2
|
||||
--------------------
|
||||
|
||||
* Setting an octal mode value to core.sharedrepository configuration to
|
||||
restrict access to the repository to group members did not work as
|
||||
advertised.
|
||||
|
||||
* A fairly large and trivial memory leak while rev-list shows list of
|
||||
reachable objects has been identified and plugged.
|
||||
|
||||
* "git-commit --interactive" did not abort when underlying "git-add -i"
|
||||
signaled a failure.
|
||||
|
||||
* git-repack (invoked from git-gc) did not work as nicely as it should in
|
||||
a repository that borrows objects from neighbours via alternates
|
||||
mechanism especially when some packs are marked with the ".keep" flag
|
||||
to prevent them from being repacked.
|
||||
|
||||
Many small documentation updates are included as well.
|
181
Documentation/RelNotes-1.6.3.txt
Normal file
181
Documentation/RelNotes-1.6.3.txt
Normal file
@ -0,0 +1,181 @@
|
||||
GIT v1.6.3 Release Notes
|
||||
========================
|
||||
|
||||
With the next major release, "git push" into a branch that is
|
||||
currently checked out will be refused by default. You can choose
|
||||
what should happen upon such a push by setting the configuration
|
||||
variable receive.denyCurrentBranch in the receiving repository.
|
||||
|
||||
To ease the transition plan, the receiving repository of such a
|
||||
push running this release will issue a big warning when the
|
||||
configuration variable is missing. Please refer to:
|
||||
|
||||
http://git.or.cz/gitwiki/GitFaq#non-bare
|
||||
http://thread.gmane.org/gmane.comp.version-control.git/107758/focus=108007
|
||||
|
||||
for more details on the reason why this change is needed and the
|
||||
transition plan.
|
||||
|
||||
For a similar reason, "git push $there :$killed" to delete the branch
|
||||
$killed in a remote repository $there, if $killed branch is the current
|
||||
branch pointed at by its HEAD, gets a large warning. You can choose what
|
||||
should happen upon such a push by setting the configuration variable
|
||||
receive.denyDeleteCurrent in the receiving repository.
|
||||
|
||||
When the user does not tell "git push" what to push, it has always
|
||||
pushed matching refs. For some people it is unexpected, and a new
|
||||
configuration variable push.default has been introduced to allow
|
||||
changing a different default behaviour. To advertise the new feature,
|
||||
a big warning is issued if this is not configured and a git push without
|
||||
arguments is attempted.
|
||||
|
||||
|
||||
Updates since v1.6.2
|
||||
--------------------
|
||||
|
||||
(subsystems)
|
||||
|
||||
* various git-svn updates.
|
||||
|
||||
(performance)
|
||||
|
||||
* many uses of lstat(2) in the codepath for "git checkout" have been
|
||||
optimized out.
|
||||
|
||||
* pruning reflog entries that are unreachable from the tip of the ref
|
||||
during "git reflog prune" (hence "git gc") was very inefficient.
|
||||
|
||||
(usability, bells and whistles)
|
||||
|
||||
* rsync:/path/to/repo can be used to run git over rsync for local
|
||||
repositories. It may not be useful in practice; meant primarily for
|
||||
testing.
|
||||
|
||||
* http transport learned to prompt and use password when fetching from or
|
||||
pushing to http://user@host.xz/ URL.
|
||||
|
||||
* (msysgit) progress output that is sent over the sideband protocol can
|
||||
be handled appropriately in Windows console.
|
||||
|
||||
* "--pretty=<style>" option to the log family of commands can now be
|
||||
spelled as "--format=<style>". In addition, --format=%formatstring
|
||||
is a short-hand for --pretty=tformat:%formatstring.
|
||||
|
||||
* "--oneline" is a synonym for "--pretty=oneline --abbrev-commit".
|
||||
|
||||
* If you realize that you botched the patch when you are editing hunks
|
||||
with the 'edit' action in git-add -i/-p, you can abort the editor to
|
||||
tell git not to apply it.
|
||||
|
||||
* The number of commits shown in "you are ahead/behind your upstream"
|
||||
messages given by "git checkout" and "git status" used to count merge
|
||||
commits; now it doesn't.
|
||||
|
||||
* @{-1} is a new way to refer to the last branch you were on introduced in
|
||||
1.6.2, but the initial implementation did not teach this to a few
|
||||
commands. Now the syntax works with "branch -m @{-1} newname".
|
||||
|
||||
* git-archive learned --output=<file> option.
|
||||
|
||||
* git-bisect shows not just the number of remaining commits whose goodness
|
||||
is unknown, but also shows the estimated number of remaining rounds.
|
||||
|
||||
* You can give --date=<format> option to git-blame.
|
||||
|
||||
* "git-branch -r" shows HEAD symref that points at a remote branch in
|
||||
interest of each tracked remote repository.
|
||||
|
||||
* "git-branch -v -v" is a new way to get list of names for branches and the
|
||||
"upstream" branch for them.
|
||||
|
||||
* git-config learned -e option to open an editor to edit the config file
|
||||
directly.
|
||||
|
||||
* git-clone runs post-checkout hook when run without --no-checkout.
|
||||
|
||||
* git-fast-export choked when seeing a tag that does not point at commit.
|
||||
|
||||
* git-for-each-ref learned a new "upstream" token.
|
||||
|
||||
* git-format-patch can be told to use attachment with a new configuration,
|
||||
format.attach.
|
||||
|
||||
* git-format-patch can be told to produce deep or shallow message threads.
|
||||
|
||||
* git-format-patch can be told to always add sign-off with a configuration
|
||||
variable.
|
||||
|
||||
* git-format-patch learned format.headers configuration to add extra
|
||||
header fields to the output. This behaviour is similar to the existing
|
||||
--add-header=<header> option of the command.
|
||||
|
||||
* git-format-patch gives human readable names to the attached files, when
|
||||
told to send patches as attachments.
|
||||
|
||||
* git-grep learned to highlight the found substrings in color.
|
||||
|
||||
* git-imap-send learned to work around Thunderbird's inability to easily
|
||||
disable format=flowed with a new configuration, imap.preformattedHTML.
|
||||
|
||||
* git-rebase can be told to rebase the series even if your branch is a
|
||||
descendant of the commit you are rebasing onto with --force-rebase
|
||||
option.
|
||||
|
||||
* git-rebase can be told to report diffstat with the --stat option.
|
||||
|
||||
* Output from git-remote command has been vastly improved.
|
||||
|
||||
* "git remote update --prune $remote" updates from the named remote and
|
||||
then prunes stale tracking branches.
|
||||
|
||||
* git-send-email learned --confirm option to review the Cc: list before
|
||||
sending the messages out.
|
||||
|
||||
(developers)
|
||||
|
||||
* Test scripts can be run under valgrind.
|
||||
|
||||
* Test scripts can be run with installed git.
|
||||
|
||||
* Makefile learned 'coverage' option to run the test suites with
|
||||
coverage tracking enabled.
|
||||
|
||||
* Building the manpages with docbook-xsl between 1.69.1 and 1.71.1 now
|
||||
requires setting DOCBOOK_SUPPRESS_SP to work around a docbook-xsl bug.
|
||||
This workaround used to be enabled by default, but causes problems
|
||||
with newer versions of docbook-xsl. In addition, there are a few more
|
||||
knobs you can tweak to work around issues with various versions of the
|
||||
docbook-xsl package. See comments in Documentation/Makefile for details.
|
||||
|
||||
Fixes since v1.6.2
|
||||
------------------
|
||||
|
||||
All of the fixes in v1.6.2.X maintenance series are included in this
|
||||
release, unless otherwise noted.
|
||||
|
||||
Here are fixes that this release has, but have not been backported to
|
||||
v1.6.2.X series.
|
||||
|
||||
* The initial checkout did not read the attributes from the .gitattribute
|
||||
file that is being checked out.
|
||||
|
||||
* "git-checkout <tree-ish> <submodule>" did not update the index entry at
|
||||
the named path; it now does.
|
||||
|
||||
* git-gc spent excessive amount of time to decide if an object appears
|
||||
in a locally existing pack (if needed, backport by merging 69e020a).
|
||||
|
||||
* "git-ls-tree" and "git-diff-tree" used a pathspec correctly when
|
||||
deciding to descend into a subdirectory but they did not match the
|
||||
individual paths correctly. This caused pathspecs "abc/d ab" to match
|
||||
"abc/0" ("abc/d" made them decide to descend into the directory "abc/",
|
||||
and then "ab" incorrectly matched "abc/0" when it shouldn't).
|
||||
|
||||
* "git-merge-recursive" was broken when a submodule entry was involved in
|
||||
a criss-cross merge situation.
|
||||
|
||||
---
|
||||
exec >/var/tmp/1
|
||||
O=v1.6.2.3-497-g54a4749
|
||||
echo O=$(git describe master)
|
||||
git shortlog --no-merges $O..master ^maint
|
@ -491,6 +491,12 @@ message, complete the addressing and subject fields, and press send.
|
||||
Gmail
|
||||
-----
|
||||
|
||||
GMail does not appear to have any way to turn off line wrapping in the web
|
||||
interface, so this will mangle any emails that you send. You can however
|
||||
use any IMAP email client to connect to the google imap server, and forward
|
||||
the emails through that. Just make sure to disable line wrapping in that
|
||||
email client. Alternatively, use "git send-email" instead.
|
||||
|
||||
Submitting properly formatted patches via Gmail is simple now that
|
||||
IMAP support is available. First, edit your ~/.gitconfig to specify your
|
||||
account settings:
|
||||
@ -503,6 +509,9 @@ account settings:
|
||||
port = 993
|
||||
sslverify = false
|
||||
|
||||
You might need to instead use: folder = "[Google Mail]/Drafts" if you get an error
|
||||
that the "Folder doesn't exist".
|
||||
|
||||
Next, ensure that your Gmail settings are correct. In "Settings" the
|
||||
"Use Unicode (UTF-8) encoding for outgoing messages" should be checked.
|
||||
|
||||
@ -513,3 +522,4 @@ command to send the patch emails to your Gmail Drafts folder.
|
||||
|
||||
Go to your Gmail account, open the Drafts folder, find the patch email, fill
|
||||
in the To: and CC: fields and send away!
|
||||
|
||||
|
@ -27,7 +27,7 @@ ifdef::backend-docbook[]
|
||||
endif::backend-docbook[]
|
||||
|
||||
ifdef::backend-docbook[]
|
||||
ifndef::docbook-xsl-172[]
|
||||
ifndef::git-asciidoc-no-roff[]
|
||||
# "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this.
|
||||
# v1.72 breaks with this because it replaces dots not in roff requests.
|
||||
[listingblock]
|
||||
@ -42,16 +42,16 @@ ifdef::doctype-manpage[]
|
||||
endif::doctype-manpage[]
|
||||
</literallayout>
|
||||
{title#}</example>
|
||||
endif::docbook-xsl-172[]
|
||||
endif::git-asciidoc-no-roff[]
|
||||
|
||||
ifdef::docbook-xsl-172[]
|
||||
ifdef::git-asciidoc-no-roff[]
|
||||
ifdef::doctype-manpage[]
|
||||
# The following two small workarounds insert a simple paragraph after screen
|
||||
[listingblock]
|
||||
<example><title>{title}</title>
|
||||
<screen>
|
||||
<literallayout>
|
||||
|
|
||||
</screen><simpara></simpara>
|
||||
</literallayout><simpara></simpara>
|
||||
{title#}</example>
|
||||
|
||||
[verseblock]
|
||||
@ -59,10 +59,11 @@ ifdef::doctype-manpage[]
|
||||
{title%}<literallayout{id? id="{id}"}>
|
||||
{title#}<literallayout>
|
||||
|
|
||||
</literallayout><simpara></simpara>
|
||||
</literallayout>
|
||||
{title#}</para></formalpara>
|
||||
{title%}<simpara></simpara>
|
||||
endif::doctype-manpage[]
|
||||
endif::docbook-xsl-172[]
|
||||
endif::git-asciidoc-no-roff[]
|
||||
endif::backend-docbook[]
|
||||
|
||||
ifdef::doctype-manpage[]
|
||||
|
@ -39,7 +39,7 @@ of lines before or after the line given by <start>.
|
||||
Show raw timestamp (Default: off).
|
||||
|
||||
-S <revs-file>::
|
||||
Use revs from revs-file instead of calling linkgit:git-rev-list[1].
|
||||
Use revisions from revs-file instead of calling linkgit:git-rev-list[1].
|
||||
|
||||
--reverse::
|
||||
Walk history forward instead of backward. Instead of showing
|
||||
@ -70,6 +70,14 @@ of lines before or after the line given by <start>.
|
||||
tree copy has the contents of the named file (specify
|
||||
`-` to make the command read from the standard input).
|
||||
|
||||
--date <format>::
|
||||
The value is one of the following alternatives:
|
||||
{relative,local,default,iso,rfc,short}. If --date is not
|
||||
provided, the value of the blame.date config variable is
|
||||
used. If the blame.date config variable is also not set, the
|
||||
iso format is used. For more information, See the discussion
|
||||
of the --date option at linkgit:git-log[1].
|
||||
|
||||
-M|<num>|::
|
||||
Detect moving lines in the file as well. When a commit
|
||||
moves a block of lines in a file (e.g. the original file
|
||||
|
@ -1,30 +0,0 @@
|
||||
<!-- callout.xsl: converts asciidoc callouts to man page format -->
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:template match="co">
|
||||
<xsl:value-of select="concat('\fB(',substring-after(@id,'-'),')\fR')"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="calloutlist">
|
||||
<xsl:text>.sp </xsl:text>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:template>
|
||||
<xsl:template match="callout">
|
||||
<xsl:value-of select="concat('\fB',substring-after(@arearefs,'-'),'. \fR')"/>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>.br </xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<!-- sorry, this is not about callouts, but attempts to work around
|
||||
spurious .sp at the tail of the line docbook stylesheets seem to add -->
|
||||
<xsl:template match="simpara">
|
||||
<xsl:variable name="content">
|
||||
<xsl:apply-templates/>
|
||||
</xsl:variable>
|
||||
<xsl:value-of select="normalize-space($content)"/>
|
||||
<xsl:if test="not(ancestor::authorblurb) and
|
||||
not(ancestor::personblurb)">
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
@ -25,7 +25,7 @@ blank lines are ignored.
|
||||
The file consists of sections and variables. A section begins with
|
||||
the name of the section in square brackets and continues until the next
|
||||
section begins. Section names are not case sensitive. Only alphanumeric
|
||||
characters, '`-`' and '`.`' are allowed in section names. Each variable
|
||||
characters, `-` and `.` are allowed in section names. Each variable
|
||||
must belong to some section, which means that there must be section
|
||||
header before first setting of a variable.
|
||||
|
||||
@ -39,7 +39,7 @@ in the section header, like in example below:
|
||||
--------
|
||||
|
||||
Subsection names can contain any characters except newline (doublequote
|
||||
'`"`' and backslash have to be escaped as '`\"`' and '`\\`',
|
||||
`"` and backslash have to be escaped as `\"` and `\\`,
|
||||
respectively) and are case sensitive. Section header cannot span multiple
|
||||
lines. Variables may belong directly to a section or to a given subsection.
|
||||
You can have `[section]` if you have `[section "subsection"]`, but you
|
||||
@ -53,7 +53,7 @@ All the other lines are recognized as setting variables, in the form
|
||||
'name = value'. If there is no equal sign on the line, the entire line
|
||||
is taken as 'name' and the variable is recognized as boolean "true".
|
||||
The variable names are case-insensitive and only alphanumeric
|
||||
characters and '`-`' are allowed. There can be more than one value
|
||||
characters and `-` are allowed. There can be more than one value
|
||||
for a given variable; we say then that variable is multivalued.
|
||||
|
||||
Leading and trailing whitespace in a variable value is discarded.
|
||||
@ -69,15 +69,15 @@ String values may be entirely or partially enclosed in double quotes.
|
||||
You need to enclose variable value in double quotes if you want to
|
||||
preserve leading or trailing whitespace, or if variable value contains
|
||||
beginning of comment characters (if it contains '#' or ';').
|
||||
Double quote '`"`' and backslash '`\`' characters in variable value must
|
||||
be escaped: use '`\"`' for '`"`' and '`\\`' for '`\`'.
|
||||
Double quote `"` and backslash `\` characters in variable value must
|
||||
be escaped: use `\"` for `"` and `\\` for `\`.
|
||||
|
||||
The following escape sequences (beside '`\"`' and '`\\`') are recognized:
|
||||
'`\n`' for newline character (NL), '`\t`' for horizontal tabulation (HT, TAB)
|
||||
and '`\b`' for backspace (BS). No other char escape sequence, nor octal
|
||||
The following escape sequences (beside `\"` and `\\`) are recognized:
|
||||
`\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB)
|
||||
and `\b` for backspace (BS). No other char escape sequence, nor octal
|
||||
char sequences are valid.
|
||||
|
||||
Variable value ending in a '`\`' is continued on the next line in the
|
||||
Variable value ending in a `\` is continued on the next line in the
|
||||
customary UNIX fashion.
|
||||
|
||||
Some variables may require special value format.
|
||||
@ -221,6 +221,11 @@ core.gitProxy::
|
||||
Can be overridden by the 'GIT_PROXY_COMMAND' environment variable
|
||||
(which always applies universally, without the special "for"
|
||||
handling).
|
||||
+
|
||||
The special string `none` can be used as the proxy command to
|
||||
specify that no proxy be used for a given domain pattern.
|
||||
This is useful for excluding servers inside a firewall from
|
||||
proxy use, while defaulting to a common proxy for external domains.
|
||||
|
||||
core.ignoreStat::
|
||||
If true, commands which modify both the working tree and the index
|
||||
@ -382,9 +387,9 @@ core.pager::
|
||||
to override git's default settings this way, you need
|
||||
to be explicit. For example, to disable the S option
|
||||
in a backward compatible manner, set `core.pager`
|
||||
to "`less -+$LESS -FRX`". This will be passed to the
|
||||
to `less -+$LESS -FRX`. This will be passed to the
|
||||
shell by git, which will translate the final command to
|
||||
"`LESS=FRSX less -+FRSX -FRX`".
|
||||
`LESS=FRSX less -+FRSX -FRX`.
|
||||
|
||||
core.whitespace::
|
||||
A comma separated list of common whitespace problems to
|
||||
@ -468,10 +473,14 @@ branch.autosetuprebase::
|
||||
This option defaults to never.
|
||||
|
||||
branch.<name>.remote::
|
||||
When in branch <name>, it tells 'git-fetch' which remote to fetch.
|
||||
If this option is not given, 'git-fetch' defaults to remote "origin".
|
||||
When in branch <name>, it tells 'git-fetch' and 'git-push' which
|
||||
remote to fetch from/push to. It defaults to `origin` if no remote is
|
||||
configured. `origin` is also used if you are not on any branch.
|
||||
|
||||
branch.<name>.merge::
|
||||
Defines, together with branch.<name>.remote, the upstream branch
|
||||
for the given branch. It tells 'git-fetch'/'git-pull' which
|
||||
branch to merge and can also affect 'git-push' (see push.default).
|
||||
When in branch <name>, it tells 'git-fetch' the default
|
||||
refspec to be marked for merging in FETCH_HEAD. The value is
|
||||
handled like the remote part of a refspec, and must match a
|
||||
@ -548,6 +557,25 @@ color.diff.<slot>::
|
||||
whitespace errors). The values of these variables may be specified as
|
||||
in color.branch.<slot>.
|
||||
|
||||
color.grep::
|
||||
When set to `always`, always highlight matches. When `false` (or
|
||||
`never`), never. When set to `true` or `auto`, use color only
|
||||
when the output is written to the terminal. Defaults to `false`.
|
||||
|
||||
color.grep.external::
|
||||
The string value of this variable is passed to an external 'grep'
|
||||
command as a command line option if match highlighting is turned
|
||||
on. If set to an empty string, no option is passed at all,
|
||||
turning off coloring for external 'grep' calls; this is the default.
|
||||
For GNU grep, set it to `--color=always` to highlight matches even
|
||||
when a pager is used.
|
||||
|
||||
color.grep.match::
|
||||
Use customized color for matches. The value of this variable
|
||||
may be specified as in color.branch.<slot>. It is passed using
|
||||
the environment variables 'GREP_COLOR' and 'GREP_COLORS' when
|
||||
calling an external 'grep'.
|
||||
|
||||
color.interactive::
|
||||
When set to `always`, always use colors for interactive prompts
|
||||
and displays (such as those used by "git-add --interactive").
|
||||
@ -677,6 +705,23 @@ format.pretty::
|
||||
See linkgit:git-log[1], linkgit:git-show[1],
|
||||
linkgit:git-whatchanged[1].
|
||||
|
||||
format.thread::
|
||||
The default threading style for 'git-format-patch'. Can be
|
||||
either a boolean value, `shallow` or `deep`. 'Shallow'
|
||||
threading makes every mail a reply to the head of the series,
|
||||
where the head is chosen from the cover letter, the
|
||||
`\--in-reply-to`, and the first patch mail, in this order.
|
||||
'Deep' threading makes every mail a reply to the previous one.
|
||||
A true boolean value is the same as `shallow`, and a false
|
||||
value disables threading.
|
||||
|
||||
format.signoff::
|
||||
A boolean value which lets you enable the `-s/--signoff` option of
|
||||
format-patch by default. *Note:* Adding the Signed-off-by: line to a
|
||||
patch should be a conscious act and means that you certify you have
|
||||
the rights to submit this work under the same open source license.
|
||||
Please see the 'SubmittingPatches' document for further discussion.
|
||||
|
||||
gc.aggressiveWindow::
|
||||
The window size parameter used in the delta compression
|
||||
algorithm used by 'git-gc --aggressive'. This defaults
|
||||
@ -1151,7 +1196,7 @@ pager.<cmd>::
|
||||
particular git subcommand when writing to a tty. If
|
||||
`\--paginate` or `\--no-pager` is specified on the command line,
|
||||
it takes precedence over this option. To disable pagination for
|
||||
all commands, set `core.pager` or 'GIT_PAGER' to "`cat`".
|
||||
all commands, set `core.pager` or `GIT_PAGER` to `cat`.
|
||||
|
||||
pull.octopus::
|
||||
The default merge strategy to use when pulling multiple branches
|
||||
@ -1160,6 +1205,23 @@ pull.octopus::
|
||||
pull.twohead::
|
||||
The default merge strategy to use when pulling a single branch.
|
||||
|
||||
push.default::
|
||||
Defines the action git push should take if no refspec is given
|
||||
on the command line, no refspec is configured in the remote, and
|
||||
no refspec is implied by any of the options given on the command
|
||||
line. Possible values are:
|
||||
+
|
||||
* `nothing` do not push anything.
|
||||
* `matching` push all matching branches.
|
||||
All branches having the same name in both ends are considered to be
|
||||
matching. This is the default.
|
||||
* `tracking` push the current branch to its upstream branch.
|
||||
* `current` push the current branch to a branch of the same name.
|
||||
|
||||
rebase.stat::
|
||||
Whether to show a diffstat of what changed upstream since the last
|
||||
rebase. False by default.
|
||||
|
||||
receive.fsckObjects::
|
||||
If it is set to true, git-receive-pack will check all received
|
||||
objects. It will abort in the case of a malformed object or a
|
||||
|
@ -16,6 +16,7 @@ body blockquote {
|
||||
html body {
|
||||
margin: 1em 5% 1em 5%;
|
||||
line-height: 1.2;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
body div {
|
||||
@ -128,6 +129,15 @@ body pre {
|
||||
|
||||
tt.literal, code.literal {
|
||||
color: navy;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
code.literal:before { content: "'"; }
|
||||
code.literal:after { content: "'"; }
|
||||
|
||||
em {
|
||||
font-style: italic;
|
||||
color: #064;
|
||||
}
|
||||
|
||||
div.literallayout p {
|
||||
@ -137,7 +147,6 @@ div.literallayout p {
|
||||
|
||||
div.literallayout {
|
||||
font-family: monospace;
|
||||
# margin: 0.5em 10% 0.5em 1em;
|
||||
margin: 0em;
|
||||
color: navy;
|
||||
border: 1px solid silver;
|
||||
@ -187,7 +196,8 @@ dt {
|
||||
}
|
||||
|
||||
dt span.term {
|
||||
font-style: italic;
|
||||
font-style: normal;
|
||||
color: navy;
|
||||
}
|
||||
|
||||
div.variablelist dd p {
|
||||
|
@ -10,6 +10,7 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]
|
||||
[--output=<file>]
|
||||
[--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
|
||||
[path...]
|
||||
|
||||
@ -22,7 +23,7 @@ prepended to the filenames in the archive.
|
||||
|
||||
'git-archive' behaves differently when given a tree ID versus when
|
||||
given a commit ID or tag ID. In the first case the current time is
|
||||
used as modification time of each file in the archive. In the latter
|
||||
used as the modification time of each file in the archive. In the latter
|
||||
case the commit time as recorded in the referenced commit object is
|
||||
used instead. Additionally the commit ID is stored in a global
|
||||
extended pax header if the tar format is used; it can be extracted
|
||||
@ -47,12 +48,15 @@ OPTIONS
|
||||
--prefix=<prefix>/::
|
||||
Prepend <prefix>/ to each filename in the archive.
|
||||
|
||||
--output=<file>::
|
||||
Write the archive to <file> instead of stdout.
|
||||
|
||||
<extra>::
|
||||
This can be any options that the archiver backend understand.
|
||||
This can be any options that the archiver backend understands.
|
||||
See next section.
|
||||
|
||||
--remote=<repo>::
|
||||
Instead of making a tar archive from local repository,
|
||||
Instead of making a tar archive from the local repository,
|
||||
retrieve a tar archive from a remote repository.
|
||||
|
||||
--exec=<git-upload-archive>::
|
||||
@ -105,7 +109,7 @@ EXAMPLES
|
||||
git archive --format=tar --prefix=junk/ HEAD | (cd /var/tmp/ && tar xf -)::
|
||||
|
||||
Create a tar archive that contains the contents of the
|
||||
latest commit on the current branch, and extracts it in
|
||||
latest commit on the current branch, and extract it in the
|
||||
`/var/tmp/junk` directory.
|
||||
|
||||
git archive --format=tar --prefix=git-1.4.0/ v1.4.0 | gzip >git-1.4.0.tar.gz::
|
||||
|
@ -3,7 +3,7 @@ git-bisect(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-bisect - Find the change that introduced a bug by binary search
|
||||
git-bisect - Find by binary search the change that introduced a bug
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
@ -39,7 +39,8 @@ help" or "git bisect -h" to get a long usage description.
|
||||
Basic bisect commands: start, bad, good
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The way you use it is:
|
||||
Using the Linux kernel tree as an example, basic use of the bisect
|
||||
command is as follows:
|
||||
|
||||
------------------------------------------------
|
||||
$ git bisect start
|
||||
@ -48,61 +49,63 @@ $ git bisect good v2.6.13-rc2 # v2.6.13-rc2 was the last version
|
||||
# tested that was good
|
||||
------------------------------------------------
|
||||
|
||||
When you give at least one bad and one good versions, it will bisect
|
||||
the revision tree and say something like:
|
||||
When you have specified at least one bad and one good version, the
|
||||
command bisects the revision tree and outputs something similar to
|
||||
the following:
|
||||
|
||||
------------------------------------------------
|
||||
Bisecting: 675 revisions left to test after this
|
||||
------------------------------------------------
|
||||
|
||||
and check out the state in the middle. Now, compile that kernel, and
|
||||
boot it. Now, let's say that this booted kernel works fine, then just
|
||||
do
|
||||
The state in the middle of the set of revisions is then checked out.
|
||||
You would now compile that kernel and boot it. If the booted kernel
|
||||
works correctly, you would then issue the following command:
|
||||
|
||||
------------------------------------------------
|
||||
$ git bisect good # this one is good
|
||||
------------------------------------------------
|
||||
|
||||
which will now say
|
||||
The output of this command would be something similar to the following:
|
||||
|
||||
------------------------------------------------
|
||||
Bisecting: 337 revisions left to test after this
|
||||
------------------------------------------------
|
||||
|
||||
and you continue along, compiling that one, testing it, and depending
|
||||
on whether it is good or bad, you say "git bisect good" or "git bisect
|
||||
bad", and ask for the next bisection.
|
||||
You keep repeating this process, compiling the tree, testing it, and
|
||||
depending on whether it is good or bad issuing the command "git bisect good"
|
||||
or "git bisect bad" to ask for the next bisection.
|
||||
|
||||
Until you have no more left, and you'll have been left with the first
|
||||
bad kernel rev in "refs/bisect/bad".
|
||||
Eventually there will be no more revisions left to bisect, and you
|
||||
will have been left with the first bad kernel revision in "refs/bisect/bad".
|
||||
|
||||
Bisect reset
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Oh, and then after you want to reset to the original head, do a
|
||||
To return to the original head after a bisect session, issue the
|
||||
following command:
|
||||
|
||||
------------------------------------------------
|
||||
$ git bisect reset
|
||||
------------------------------------------------
|
||||
|
||||
to get back to the original branch, instead of being on the bisection
|
||||
commit ("git bisect start" will do that for you too, actually: it will
|
||||
reset the bisection state).
|
||||
This resets the tree to the original branch instead of being on the
|
||||
bisection commit ("git bisect start" will also do that, as it resets
|
||||
the bisection state).
|
||||
|
||||
Bisect visualize
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
During the bisection process, you can say
|
||||
To see the currently remaining suspects in 'gitk', issue the following
|
||||
command during the bisection process:
|
||||
|
||||
------------
|
||||
$ git bisect visualize
|
||||
------------
|
||||
|
||||
to see the currently remaining suspects in 'gitk'. `visualize` is a bit
|
||||
too long to type and `view` is provided as a synonym.
|
||||
`view` may also be used as a synonym for `visualize`.
|
||||
|
||||
If 'DISPLAY' environment variable is not set, 'git log' is used
|
||||
instead. You can even give command line options such as `-p` and
|
||||
If the 'DISPLAY' environment variable is not set, 'git log' is used
|
||||
instead. You can also give command line options such as `-p` and
|
||||
`--stat`.
|
||||
|
||||
------------
|
||||
@ -112,57 +115,58 @@ $ git bisect view --stat
|
||||
Bisect log and bisect replay
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The good/bad input is logged, and
|
||||
After having marked revisions as good or bad, issue the following
|
||||
command to show what has been done so far:
|
||||
|
||||
------------
|
||||
$ git bisect log
|
||||
------------
|
||||
|
||||
shows what you have done so far. You can truncate its output somewhere
|
||||
and save it in a file, and run
|
||||
If you discover that you made a mistake in specifying the status of a
|
||||
revision, you can save the output of this command to a file, edit it to
|
||||
remove the incorrect entries, and then issue the following commands to
|
||||
return to a corrected state:
|
||||
|
||||
------------
|
||||
$ git bisect reset
|
||||
$ git bisect replay that-file
|
||||
------------
|
||||
|
||||
if you find later you made a mistake telling good/bad about a
|
||||
revision.
|
||||
|
||||
Avoiding to test a commit
|
||||
Avoiding testing a commit
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If in a middle of bisect session, you know what the bisect suggested
|
||||
to try next is not a good one to test (e.g. the change the commit
|
||||
If, in the middle of a bisect session, you know that the next suggested
|
||||
revision is not a good one to test (e.g. the change the commit
|
||||
introduces is known not to work in your environment and you know it
|
||||
does not have anything to do with the bug you are chasing), you may
|
||||
want to find a near-by commit and try that instead.
|
||||
want to find a nearby commit and try that instead.
|
||||
|
||||
It goes something like this:
|
||||
For example:
|
||||
|
||||
------------
|
||||
$ git bisect good/bad # previous round was good/bad.
|
||||
$ git bisect good/bad # previous round was good or bad.
|
||||
Bisecting: 337 revisions left to test after this
|
||||
$ git bisect visualize # oops, that is uninteresting.
|
||||
$ git reset --hard HEAD~3 # try 3 revs before what
|
||||
$ git reset --hard HEAD~3 # try 3 revisions before what
|
||||
# was suggested
|
||||
------------
|
||||
|
||||
Then compile and test the one you chose to try. After that, tell
|
||||
bisect what the result was as usual.
|
||||
Then compile and test the chosen revision, and afterwards mark
|
||||
the revision as good or bad in the usual manner.
|
||||
|
||||
Bisect skip
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Instead of choosing by yourself a nearby commit, you may just want git
|
||||
to do it for you using:
|
||||
Instead of choosing by yourself a nearby commit, you can ask git
|
||||
to do it for you by issuing the command:
|
||||
|
||||
------------
|
||||
$ git bisect skip # Current version cannot be tested
|
||||
------------
|
||||
|
||||
But computing the commit to test may be slower afterwards and git may
|
||||
eventually not be able to tell the first bad among a bad and one or
|
||||
more "skip"ped commits.
|
||||
eventually not be able to tell the first bad commit among a bad commit
|
||||
and one or more skipped commits.
|
||||
|
||||
You can even skip a range of commits, instead of just one commit,
|
||||
using the "'<commit1>'..'<commit2>'" notation. For example:
|
||||
@ -171,33 +175,34 @@ using the "'<commit1>'..'<commit2>'" notation. For example:
|
||||
$ git bisect skip v2.5..v2.6
|
||||
------------
|
||||
|
||||
would mean that no commit between `v2.5` excluded and `v2.6` included
|
||||
can be tested.
|
||||
This tells the bisect process that no commit after `v2.5`, up to and
|
||||
including `v2.6`, should be tested.
|
||||
|
||||
Note that if you want to also skip the first commit of a range you can
|
||||
use something like:
|
||||
Note that if you also want to skip the first commit of the range you
|
||||
would issue the command:
|
||||
|
||||
------------
|
||||
$ git bisect skip v2.5 v2.5..v2.6
|
||||
------------
|
||||
|
||||
and the commit pointed to by `v2.5` will be skipped too.
|
||||
This tells the bisect process that the commits between `v2.5` included
|
||||
and `v2.6` included should be skipped.
|
||||
|
||||
|
||||
Cutting down bisection by giving more parameters to bisect start
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can further cut down the number of trials if you know what part of
|
||||
the tree is involved in the problem you are tracking down, by giving
|
||||
paths parameters when you say `bisect start`, like this:
|
||||
You can further cut down the number of trials, if you know what part of
|
||||
the tree is involved in the problem you are tracking down, by specifying
|
||||
path parameters when issuing the `bisect start` command:
|
||||
|
||||
------------
|
||||
$ git bisect start -- arch/i386 include/asm-i386
|
||||
------------
|
||||
|
||||
If you know beforehand more than one good commits, you can narrow the
|
||||
bisect space down without doing the whole tree checkout every time you
|
||||
give good commits. You give the bad revision immediately after `start`
|
||||
and then you give all the good revisions you have:
|
||||
If you know beforehand more than one good commit, you can narrow the
|
||||
bisect space down by specifying all of the good commits immediately after
|
||||
the bad commit when issuing the `bisect start` command:
|
||||
|
||||
------------
|
||||
$ git bisect start v2.6.20-rc6 v2.6.20-rc4 v2.6.20-rc1 --
|
||||
@ -209,38 +214,38 @@ Bisect run
|
||||
~~~~~~~~~~
|
||||
|
||||
If you have a script that can tell if the current source code is good
|
||||
or bad, you can automatically bisect using:
|
||||
or bad, you can bisect by issuing the command:
|
||||
|
||||
------------
|
||||
$ git bisect run my_script
|
||||
$ git bisect run my_script arguments
|
||||
------------
|
||||
|
||||
Note that the "run" script (`my_script` in the above example) should
|
||||
exit with code 0 in case the current source code is good. Exit with a
|
||||
Note that the script (`my_script` in the above example) should
|
||||
exit with code 0 if the current source code is good, and exit with a
|
||||
code between 1 and 127 (inclusive), except 125, if the current
|
||||
source code is bad.
|
||||
|
||||
Any other exit code will abort the automatic bisect process. (A
|
||||
program that does "exit(-1)" leaves $? = 255, see exit(3) manual page,
|
||||
the value is chopped with "& 0377".)
|
||||
Any other exit code will abort the bisect process. It should be noted
|
||||
that a program that terminates via "exit(-1)" leaves $? = 255, (see the
|
||||
exit(3) manual page), as the value is chopped with "& 0377".
|
||||
|
||||
The special exit code 125 should be used when the current source code
|
||||
cannot be tested. If the "run" script exits with this code, the current
|
||||
revision will be skipped, see `git bisect skip` above.
|
||||
cannot be tested. If the script exits with this code, the current
|
||||
revision will be skipped (see `git bisect skip` above).
|
||||
|
||||
You may often find that during bisect you want to have near-constant
|
||||
tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or
|
||||
"revision that does not have this commit needs this patch applied to
|
||||
work around other problem this bisection is not interested in")
|
||||
applied to the revision being tested.
|
||||
You may often find that during a bisect session you want to have
|
||||
temporary modifications (e.g. s/#define DEBUG 0/#define DEBUG 1/ in a
|
||||
header file, or "revision that does not have this commit needs this
|
||||
patch applied to work around another problem this bisection is not
|
||||
interested in") applied to the revision being tested.
|
||||
|
||||
To cope with such a situation, after the inner 'git bisect' finds the
|
||||
next revision to test, with the "run" script, you can apply that tweak
|
||||
before compiling, run the real test, and after the test decides if the
|
||||
revision (possibly with the needed tweaks) passed the test, rewind the
|
||||
tree to the pristine state. Finally the "run" script can exit with
|
||||
the status of the real test to let the "git bisect run" command loop to
|
||||
determine the outcome.
|
||||
next revision to test, the script can apply the patch
|
||||
before compiling, run the real test, and afterwards decide if the
|
||||
revision (possibly with the needed patch) passed the test and then
|
||||
rewind the tree to the pristine state. Finally the script should exit
|
||||
with the status of the real test to let the "git bisect run" command loop
|
||||
determine the eventual outcome of the bisect session.
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
@ -252,44 +257,60 @@ $ git bisect start HEAD v1.2 -- # HEAD is bad, v1.2 is good
|
||||
$ git bisect run make # "make" builds the app
|
||||
------------
|
||||
|
||||
* Automatically bisect a test failure between origin and HEAD:
|
||||
+
|
||||
------------
|
||||
$ git bisect start HEAD origin -- # HEAD is bad, origin is good
|
||||
$ git bisect run make test # "make test" builds and tests
|
||||
------------
|
||||
|
||||
* Automatically bisect a broken test suite:
|
||||
+
|
||||
------------
|
||||
$ cat ~/test.sh
|
||||
#!/bin/sh
|
||||
make || exit 125 # this "skip"s broken builds
|
||||
make || exit 125 # this skips broken builds
|
||||
make test # "make test" runs the test suite
|
||||
$ git bisect start v1.3 v1.1 -- # v1.3 is bad, v1.1 is good
|
||||
$ git bisect run ~/test.sh
|
||||
------------
|
||||
+
|
||||
Here we use a "test.sh" custom script. In this script, if "make"
|
||||
fails, we "skip" the current commit.
|
||||
fails, we skip the current commit.
|
||||
+
|
||||
It's safer to use a custom script outside the repo to prevent
|
||||
It is safer to use a custom script outside the repository to prevent
|
||||
interactions between the bisect, make and test processes and the
|
||||
script.
|
||||
+
|
||||
And "make test" should "exit 0", if the test suite passes, and
|
||||
"exit 1" (for example) otherwise.
|
||||
"make test" should "exit 0", if the test suite passes, and
|
||||
"exit 1" otherwise.
|
||||
|
||||
* Automatically bisect a broken test case:
|
||||
+
|
||||
------------
|
||||
$ cat ~/test.sh
|
||||
#!/bin/sh
|
||||
make || exit 125 # this "skip"s broken builds
|
||||
make || exit 125 # this skips broken builds
|
||||
~/check_test_case.sh # does the test case passes ?
|
||||
$ git bisect start HEAD HEAD~10 -- # culprit is among the last 10
|
||||
$ git bisect run ~/test.sh
|
||||
------------
|
||||
+
|
||||
Here "check_test_case.sh" should "exit 0", if the test case passes,
|
||||
and "exit 1" (for example) otherwise.
|
||||
Here "check_test_case.sh" should "exit 0" if the test case passes,
|
||||
and "exit 1" otherwise.
|
||||
+
|
||||
It's safer if both "test.sh" and "check_test_case.sh" scripts are
|
||||
outside the repo to prevent interactions between the bisect, make and
|
||||
test processes and the scripts.
|
||||
It is safer if both "test.sh" and "check_test_case.sh" scripts are
|
||||
outside the repository to prevent interactions between the bisect,
|
||||
make and test processes and the scripts.
|
||||
|
||||
* Automatically bisect a broken test suite:
|
||||
+
|
||||
------------
|
||||
$ git bisect start HEAD HEAD~10 -- # culprit is among the last 10
|
||||
$ git bisect run sh -c "make || exit 125; ~/check_test_case.sh"
|
||||
------------
|
||||
+
|
||||
Does the same as the previous example, but on a single line.
|
||||
|
||||
Author
|
||||
------
|
||||
|
@ -18,9 +18,9 @@ DESCRIPTION
|
||||
Annotates each line in the given file with information from the revision which
|
||||
last modified the line. Optionally, start annotating from the given revision.
|
||||
|
||||
Also it can limit the range of lines annotated.
|
||||
The command can also limit the range of lines annotated.
|
||||
|
||||
This report doesn't tell you anything about lines which have been deleted or
|
||||
The report does not tell you anything about lines which have been deleted or
|
||||
replaced; you need to use a tool such as 'git-diff' or the "pickaxe"
|
||||
interface briefly mentioned in the following paragraph.
|
||||
|
||||
@ -48,26 +48,26 @@ include::blame-options.txt[]
|
||||
lines between files (see `-C`) and lines moved within a
|
||||
file (see `-M`). The first number listed is the score.
|
||||
This is the number of alphanumeric characters detected
|
||||
to be moved between or within files. This must be above
|
||||
as having been moved between or within files. This must be above
|
||||
a certain threshold for 'git-blame' to consider those lines
|
||||
of code to have been moved.
|
||||
|
||||
-f::
|
||||
--show-name::
|
||||
Show filename in the original commit. By default
|
||||
filename is shown if there is any line that came from a
|
||||
file with different name, due to rename detection.
|
||||
Show the filename in the original commit. By default
|
||||
the filename is shown if there is any line that came from a
|
||||
file with a different name, due to rename detection.
|
||||
|
||||
-n::
|
||||
--show-number::
|
||||
Show line number in the original commit (Default: off).
|
||||
Show the line number in the original commit (Default: off).
|
||||
|
||||
-s::
|
||||
Suppress author name and timestamp from the output.
|
||||
Suppress the author name and timestamp from the output.
|
||||
|
||||
-w::
|
||||
Ignore whitespace when comparing parent's version and
|
||||
child's to find where the lines came from.
|
||||
Ignore whitespace when comparing the parent's version and
|
||||
the child's to find where the lines came from.
|
||||
|
||||
|
||||
THE PORCELAIN FORMAT
|
||||
@ -79,17 +79,17 @@ header at the minimum has the first line which has:
|
||||
- 40-byte SHA-1 of the commit the line is attributed to;
|
||||
- the line number of the line in the original file;
|
||||
- the line number of the line in the final file;
|
||||
- on a line that starts a group of line from a different
|
||||
- on a line that starts a group of lines from a different
|
||||
commit than the previous one, the number of lines in this
|
||||
group. On subsequent lines this field is absent.
|
||||
|
||||
This header line is followed by the following information
|
||||
at least once for each commit:
|
||||
|
||||
- author name ("author"), email ("author-mail"), time
|
||||
- the author name ("author"), email ("author-mail"), time
|
||||
("author-time"), and timezone ("author-tz"); similarly
|
||||
for committer.
|
||||
- filename in the commit the line is attributed to.
|
||||
- the filename in the commit that the line is attributed to.
|
||||
- the first line of the commit log message ("summary").
|
||||
|
||||
The contents of the actual line is output after the above
|
||||
@ -100,23 +100,23 @@ header elements later.
|
||||
SPECIFYING RANGES
|
||||
-----------------
|
||||
|
||||
Unlike 'git-blame' and 'git-annotate' in older git, the extent
|
||||
of annotation can be limited to both line ranges and revision
|
||||
Unlike 'git-blame' and 'git-annotate' in older versions of git, the extent
|
||||
of the annotation can be limited to both line ranges and revision
|
||||
ranges. When you are interested in finding the origin for
|
||||
ll. 40-60 for file `foo`, you can use `-L` option like these
|
||||
lines 40-60 for file `foo`, you can use the `-L` option like so
|
||||
(they mean the same thing -- both ask for 21 lines starting at
|
||||
line 40):
|
||||
|
||||
git blame -L 40,60 foo
|
||||
git blame -L 40,+21 foo
|
||||
|
||||
Also you can use regular expression to specify the line range.
|
||||
Also you can use a regular expression to specify the line range:
|
||||
|
||||
git blame -L '/^sub hello {/,/^}$/' foo
|
||||
|
||||
would limit the annotation to the body of `hello` subroutine.
|
||||
which limits the annotation to the body of the `hello` subroutine.
|
||||
|
||||
When you are not interested in changes older than the version
|
||||
When you are not interested in changes older than version
|
||||
v2.6.18, or changes older than 3 weeks, you can use revision
|
||||
range specifiers similar to 'git-rev-list':
|
||||
|
||||
@ -129,7 +129,7 @@ commit v2.6.18 or the most recent commit that is more than 3
|
||||
weeks old in the above example) are blamed for that range
|
||||
boundary commit.
|
||||
|
||||
A particularly useful way is to see if an added file have lines
|
||||
A particularly useful way is to see if an added file has lines
|
||||
created by copy-and-paste from existing files. Sometimes this
|
||||
indicates that the developer was being sloppy and did not
|
||||
refactor the code properly. You can first find the commit that
|
||||
@ -162,26 +162,26 @@ annotated.
|
||||
+
|
||||
Line numbers count from 1.
|
||||
|
||||
. The first time that commit shows up in the stream, it has various
|
||||
. The first time that a commit shows up in the stream, it has various
|
||||
other information about it printed out with a one-word tag at the
|
||||
beginning of each line about that "extended commit info" (author,
|
||||
email, committer, dates, summary etc).
|
||||
beginning of each line describing the extra commit information (author,
|
||||
email, committer, dates, summary, etc.).
|
||||
|
||||
. Unlike Porcelain format, the filename information is always
|
||||
. Unlike the Porcelain format, the filename information is always
|
||||
given and terminates the entry:
|
||||
|
||||
"filename" <whitespace-quoted-filename-goes-here>
|
||||
+
|
||||
and thus it's really quite easy to parse for some line- and word-oriented
|
||||
and thus it is really quite easy to parse for some line- and word-oriented
|
||||
parser (which should be quite natural for most scripting languages).
|
||||
+
|
||||
[NOTE]
|
||||
For people who do parsing: to make it more robust, just ignore any
|
||||
lines in between the first and last one ("<sha1>" and "filename" lines)
|
||||
where you don't recognize the tag-words (or care about that particular
|
||||
lines between the first and last one ("<sha1>" and "filename" lines)
|
||||
where you do not recognize the tag words (or care about that particular
|
||||
one) at the beginning of the "extended information" lines. That way, if
|
||||
there is ever added information (like the commit encoding or extended
|
||||
commit commentary), a blame viewer won't ever care.
|
||||
commit commentary), a blame viewer will not care.
|
||||
|
||||
|
||||
MAPPING AUTHORS
|
||||
|
@ -18,19 +18,19 @@ SYNOPSIS
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
With no arguments, existing branches are listed, the current branch will
|
||||
With no arguments, existing branches are listed and the current branch will
|
||||
be highlighted with an asterisk. Option `-r` causes the remote-tracking
|
||||
branches to be listed, and option `-a` shows both.
|
||||
|
||||
With `--contains`, shows only the branches that contains the named commit
|
||||
(in other words, the branches whose tip commits are descendant of the
|
||||
With `--contains`, shows only the branches that contain the named commit
|
||||
(in other words, the branches whose tip commits are descendants of the
|
||||
named commit). With `--merged`, only branches merged into the named
|
||||
commit (i.e. the branches whose tip commits are reachable from the named
|
||||
commit) will be listed. With `--no-merged` only branches not merged into
|
||||
the named commit will be listed. Missing <commit> argument defaults to
|
||||
'HEAD' (i.e. the tip of the current branch).
|
||||
the named commit will be listed. If the <commit> argument is missing it
|
||||
defaults to 'HEAD' (i.e. the tip of the current branch).
|
||||
|
||||
In its second form, a new branch named <branchname> will be created.
|
||||
In the command's second form, a new branch named <branchname> will be created.
|
||||
It will start out with a head equal to the one given as <start-point>.
|
||||
If no <start-point> is given, the branch will be created with a head
|
||||
equal to that of the currently checked out branch.
|
||||
@ -57,9 +57,9 @@ has a reflog then the reflog will also be deleted.
|
||||
|
||||
Use -r together with -d to delete remote-tracking branches. Note, that it
|
||||
only makes sense to delete remote-tracking branches if they no longer exist
|
||||
in remote repository or if 'git-fetch' was configured not to fetch
|
||||
them again. See also 'prune' subcommand of linkgit:git-remote[1] for way to
|
||||
clean up all obsolete remote-tracking branches.
|
||||
in the remote repository or if 'git-fetch' was configured not to fetch
|
||||
them again. See also the 'prune' subcommand of linkgit:git-remote[1] for a
|
||||
way to clean up all obsolete remote-tracking branches.
|
||||
|
||||
|
||||
OPTIONS
|
||||
@ -76,14 +76,14 @@ OPTIONS
|
||||
based sha1 expressions such as "<branchname>@\{yesterday}".
|
||||
|
||||
-f::
|
||||
Force the creation of a new branch even if it means deleting
|
||||
a branch that already exists with the same name.
|
||||
Reset <branchname> to <startpoint> if <branchname> exists
|
||||
already. Without `-f` 'git-branch' refuses to change an existing branch.
|
||||
|
||||
-m::
|
||||
Move/rename a branch and the corresponding reflog.
|
||||
|
||||
-M::
|
||||
Move/rename a branch even if the new branchname already exists.
|
||||
Move/rename a branch even if the new branch name already exists.
|
||||
|
||||
--color::
|
||||
Color branches to highlight current, local, and remote branches.
|
||||
@ -100,20 +100,22 @@ OPTIONS
|
||||
|
||||
-v::
|
||||
--verbose::
|
||||
Show sha1 and commit subject line for each head.
|
||||
Show sha1 and commit subject line for each head, along with
|
||||
relationship to upstream branch (if any). If given twice, print
|
||||
the name of the upstream branch, as well.
|
||||
|
||||
--abbrev=<length>::
|
||||
Alter minimum display length for sha1 in output listing,
|
||||
default value is 7.
|
||||
Alter the sha1's minimum display length in the output listing.
|
||||
The default value is 7.
|
||||
|
||||
--no-abbrev::
|
||||
Display the full sha1s in output listing rather than abbreviating them.
|
||||
Display the full sha1s in the output listing rather than abbreviating them.
|
||||
|
||||
--track::
|
||||
When creating a new branch, set up configuration so that 'git-pull'
|
||||
When creating a new branch, set up the configuration so that 'git-pull'
|
||||
will automatically retrieve data from the start point, which must be
|
||||
a branch. Use this if you always pull from the same upstream branch
|
||||
into the new branch, and if you don't want to use "git pull
|
||||
into the new branch, and if you do not want to use "git pull
|
||||
<repository> <refspec>" explicitly. This behavior is the default
|
||||
when the start point is a remote branch. Set the
|
||||
branch.autosetupmerge configuration variable to `false` if you want
|
||||
@ -149,13 +151,13 @@ OPTIONS
|
||||
|
||||
<newbranch>::
|
||||
The new name for an existing branch. The same restrictions as for
|
||||
<branchname> applies.
|
||||
<branchname> apply.
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Start development off of a known tag::
|
||||
Start development from a known tag::
|
||||
+
|
||||
------------
|
||||
$ git clone git://git.kernel.org/pub/scm/.../linux-2.6 my2.6
|
||||
@ -167,7 +169,7 @@ $ git checkout my2.6.14
|
||||
<1> This step and the next one could be combined into a single step with
|
||||
"checkout -b my2.6.14 v2.6.14".
|
||||
|
||||
Delete unneeded branch::
|
||||
Delete an unneeded branch::
|
||||
+
|
||||
------------
|
||||
$ git clone git://git.kernel.org/.../git.git my.git
|
||||
@ -176,21 +178,21 @@ $ git branch -d -r origin/todo origin/html origin/man <1>
|
||||
$ git branch -D test <2>
|
||||
------------
|
||||
+
|
||||
<1> Delete remote-tracking branches "todo", "html", "man". Next 'fetch' or
|
||||
'pull' will create them again unless you configure them not to. See
|
||||
linkgit:git-fetch[1].
|
||||
<2> Delete "test" branch even if the "master" branch (or whichever branch is
|
||||
currently checked out) does not have all commits from test branch.
|
||||
<1> Delete the remote-tracking branches "todo", "html" and "man". The next
|
||||
'fetch' or 'pull' will create them again unless you configure them not to.
|
||||
See linkgit:git-fetch[1].
|
||||
<2> Delete the "test" branch even if the "master" branch (or whichever branch
|
||||
is currently checked out) does not have all commits from the test branch.
|
||||
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
If you are creating a branch that you want to immediately checkout, it's
|
||||
If you are creating a branch that you want to checkout immediately, it is
|
||||
easier to use the git checkout command with its `-b` option to create
|
||||
a branch and check it out with a single command.
|
||||
|
||||
The options `--contains`, `--merged` and `--no-merged` serves three related
|
||||
The options `--contains`, `--merged` and `--no-merged` serve three related
|
||||
but different purposes:
|
||||
|
||||
- `--contains <commit>` is used to find all branches which will need
|
||||
|
@ -19,13 +19,13 @@ DESCRIPTION
|
||||
|
||||
Some workflows require that one or more branches of development on one
|
||||
machine be replicated on another machine, but the two machines cannot
|
||||
be directly connected so the interactive git protocols (git, ssh,
|
||||
rsync, http) cannot be used. This command provides support for
|
||||
be directly connected, and therefore the interactive git protocols (git,
|
||||
ssh, rsync, http) cannot be used. This command provides support for
|
||||
'git-fetch' and 'git-pull' to operate by packaging objects and references
|
||||
in an archive at the originating machine, then importing those into
|
||||
another repository using 'git-fetch' and 'git-pull'
|
||||
after moving the archive by some means (i.e., by sneakernet). As no
|
||||
direct connection between repositories exists, the user must specify a
|
||||
direct connection between the repositories exists, the user must specify a
|
||||
basis for the bundle that is held by the destination repository: the
|
||||
bundle assumes that all objects in the basis are already in the
|
||||
destination repository.
|
||||
@ -43,7 +43,7 @@ verify <file>::
|
||||
bundle format itself as well as checking that the prerequisite
|
||||
commits exist and are fully linked in the current repository.
|
||||
'git-bundle' prints a list of missing commits, if any, and exits
|
||||
with non-zero status.
|
||||
with a non-zero status.
|
||||
|
||||
list-heads <file>::
|
||||
Lists the references defined in the bundle. If followed by a
|
||||
@ -53,14 +53,14 @@ list-heads <file>::
|
||||
unbundle <file>::
|
||||
Passes the objects in the bundle to 'git-index-pack'
|
||||
for storage in the repository, then prints the names of all
|
||||
defined references. If a reflist is given, only references
|
||||
matching those in the given list are printed. This command is
|
||||
defined references. If a list of references is given, only
|
||||
references matching those in the list are printed. This command is
|
||||
really plumbing, intended to be called only by 'git-fetch'.
|
||||
|
||||
[git-rev-list-args...]::
|
||||
A list of arguments, acceptable to 'git-rev-parse' and
|
||||
'git-rev-list', that specify the specific objects and references
|
||||
to transport. For example, "master~10..master" causes the
|
||||
'git-rev-list', that specifies the specific objects and references
|
||||
to transport. For example, `master\~10..master` causes the
|
||||
current master reference to be packaged along with all objects
|
||||
added since its 10th ancestor commit. There is no explicit
|
||||
limit to the number of references and objects that may be
|
||||
@ -71,24 +71,24 @@ unbundle <file>::
|
||||
A list of references used to limit the references reported as
|
||||
available. This is principally of use to 'git-fetch', which
|
||||
expects to receive only those references asked for and not
|
||||
necessarily everything in the pack (in this case, 'git-bundle' is
|
||||
acting like 'git-fetch-pack').
|
||||
necessarily everything in the pack (in this case, 'git-bundle' acts
|
||||
like 'git-fetch-pack').
|
||||
|
||||
SPECIFYING REFERENCES
|
||||
---------------------
|
||||
|
||||
'git-bundle' will only package references that are shown by
|
||||
'git-show-ref': this includes heads, tags, and remote heads. References
|
||||
such as master~1 cannot be packaged, but are perfectly suitable for
|
||||
such as `master\~1` cannot be packaged, but are perfectly suitable for
|
||||
defining the basis. More than one reference may be packaged, and more
|
||||
than one basis can be specified. The objects packaged are those not
|
||||
contained in the union of the given bases. Each basis can be
|
||||
specified explicitly (e.g., ^master~10), or implicitly (e.g.,
|
||||
master~10..master, --since=10.days.ago master).
|
||||
specified explicitly (e.g. `^master\~10`), or implicitly (e.g.
|
||||
`master\~10..master`, `--since=10.days.ago master`).
|
||||
|
||||
It is very important that the basis used be held by the destination.
|
||||
It is okay to err on the side of conservatism, causing the bundle file
|
||||
to contain objects already in the destination as these are ignored
|
||||
It is okay to err on the side of caution, causing the bundle file
|
||||
to contain objects already in the destination, as these are ignored
|
||||
when unpacking at the destination.
|
||||
|
||||
EXAMPLE
|
||||
@ -97,13 +97,13 @@ EXAMPLE
|
||||
Assume you want to transfer the history from a repository R1 on machine A
|
||||
to another repository R2 on machine B.
|
||||
For whatever reason, direct connection between A and B is not allowed,
|
||||
but we can move data from A to B via some mechanism (CD, email, etc).
|
||||
We want to update R2 with developments made on branch master in R1.
|
||||
but we can move data from A to B via some mechanism (CD, email, etc.).
|
||||
We want to update R2 with development made on the branch master in R1.
|
||||
|
||||
To bootstrap the process, you can first create a bundle that doesn't have
|
||||
any basis. You can use a tag to remember up to what commit you sent out
|
||||
in order to make it easy to later update the other repository with
|
||||
incremental bundle,
|
||||
To bootstrap the process, you can first create a bundle that does not have
|
||||
any basis. You can use a tag to remember up to what commit you last
|
||||
processed, in order to make it easy to later update the other repository
|
||||
with an incremental bundle:
|
||||
|
||||
----------------
|
||||
machineA$ cd R1
|
||||
@ -111,17 +111,17 @@ machineA$ git bundle create file.bundle master
|
||||
machineA$ git tag -f lastR2bundle master
|
||||
----------------
|
||||
|
||||
Then you sneakernet file.bundle to the target machine B. Because you don't
|
||||
have to have any object to extract objects from such a bundle, not only
|
||||
you can fetch/pull from a bundle, you can clone from it as if it was a
|
||||
remote repository.
|
||||
Then you transfer file.bundle to the target machine B. If you are creating
|
||||
the repository on machine B, then you can clone from the bundle as if it
|
||||
were a remote repository instead of creating an empty repository and then
|
||||
pulling or fetching objects from the bundle:
|
||||
|
||||
----------------
|
||||
machineB$ git clone /home/me/tmp/file.bundle R2
|
||||
----------------
|
||||
|
||||
This will define a remote called "origin" in the resulting repository that
|
||||
lets you fetch and pull from the bundle. $GIT_DIR/config file in R2 may
|
||||
lets you fetch and pull from the bundle. The $GIT_DIR/config file in R2 will
|
||||
have an entry like this:
|
||||
|
||||
------------------------
|
||||
@ -130,12 +130,12 @@ have an entry like this:
|
||||
fetch = refs/heads/*:refs/remotes/origin/*
|
||||
------------------------
|
||||
|
||||
You can fetch/pull to update the resulting mine.git repository after
|
||||
replacing the bundle you store at /home/me/tmp/file.bundle with incremental
|
||||
updates from here on.
|
||||
To update the resulting mine.git repository, you can fetch or pull after
|
||||
replacing the bundle stored at /home/me/tmp/file.bundle with incremental
|
||||
updates.
|
||||
|
||||
After working more in the original repository, you can create an
|
||||
incremental bundle to update the other:
|
||||
After working some more in the original repository, you can create an
|
||||
incremental bundle to update the other repository:
|
||||
|
||||
----------------
|
||||
machineA$ cd R1
|
||||
@ -143,8 +143,8 @@ machineA$ git bundle create file.bundle lastR2bundle..master
|
||||
machineA$ git tag -f lastR2bundle master
|
||||
----------------
|
||||
|
||||
and sneakernet it to the other machine to replace /home/me/tmp/file.bundle,
|
||||
and pull from it.
|
||||
You then transfer the bundle to the other machine to replace
|
||||
/home/me/tmp/file.bundle, and pull from it.
|
||||
|
||||
----------------
|
||||
machineB$ cd R2
|
||||
@ -152,49 +152,49 @@ machineB$ git pull
|
||||
----------------
|
||||
|
||||
If you know up to what commit the intended recipient repository should
|
||||
have the necessary objects for, you can use that knowledge to specify the
|
||||
have the necessary objects, you can use that knowledge to specify the
|
||||
basis, giving a cut-off point to limit the revisions and objects that go
|
||||
in the resulting bundle. The previous example used lastR2bundle tag
|
||||
for this purpose, but you can use other options you would give to
|
||||
for this purpose, but you can use any other options that you would give to
|
||||
the linkgit:git-log[1] command. Here are more examples:
|
||||
|
||||
You can use a tag that is present in both.
|
||||
You can use a tag that is present in both:
|
||||
|
||||
----------------
|
||||
$ git bundle create mybundle v1.0.0..master
|
||||
----------------
|
||||
|
||||
You can use a basis based on time.
|
||||
You can use a basis based on time:
|
||||
|
||||
----------------
|
||||
$ git bundle create mybundle --since=10.days master
|
||||
----------------
|
||||
|
||||
Or you can use the number of commits.
|
||||
You can use the number of commits:
|
||||
|
||||
----------------
|
||||
$ git bundle create mybundle -10 master
|
||||
----------------
|
||||
|
||||
You can run `git-bundle verify` to see if you can extract from a bundle
|
||||
that was created with a basis.
|
||||
that was created with a basis:
|
||||
|
||||
----------------
|
||||
$ git bundle verify mybundle
|
||||
----------------
|
||||
|
||||
This will list what commits you must have in order to extract from the
|
||||
bundle and will error out if you don't have them.
|
||||
bundle and will error out if you do not have them.
|
||||
|
||||
A bundle from a recipient repository's point of view is just like a
|
||||
regular repository it fetches/pulls from. You can for example map
|
||||
refs, like this example, when fetching:
|
||||
regular repository which it fetches or pulls from. You can, for example, map
|
||||
references when fetching:
|
||||
|
||||
----------------
|
||||
$ git fetch mybundle master:localRef
|
||||
----------------
|
||||
|
||||
Or see what refs it offers.
|
||||
You can also see what references it offers.
|
||||
|
||||
----------------
|
||||
$ git ls-remote mybundle
|
||||
|
@ -3,7 +3,7 @@ git-cat-file(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-cat-file - Provide content or type/size information for repository objects
|
||||
git-cat-file - Provide content or type and size information for repository objects
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
@ -14,19 +14,19 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
In the first form, provides content or type of objects in the repository. The
|
||||
type is required unless '-t' or '-p' is used to find the object type, or '-s'
|
||||
is used to find the object size.
|
||||
In its first form, the command provides the content or the type of an object in
|
||||
the repository. The type is required unless '-t' or '-p' is used to find the
|
||||
object type, or '-s' is used to find the object size.
|
||||
|
||||
In the second form, a list of object (separated by LFs) is provided on stdin,
|
||||
and the SHA1, type, and size of each object is printed on stdout.
|
||||
In the second form, a list of objects (separated by linefeeds) is provided on
|
||||
stdin, and the SHA1, type, and size of each object is printed on stdout.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
<object>::
|
||||
The name of the object to show.
|
||||
For a more complete list of ways to spell object names, see
|
||||
"SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
|
||||
the "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
|
||||
|
||||
-t::
|
||||
Instead of the content, show the object type identified by
|
||||
@ -56,8 +56,8 @@ OPTIONS
|
||||
stdin. May not be combined with any other options or arguments.
|
||||
|
||||
--batch-check::
|
||||
Print the SHA1, type, and size of each object provided on stdin. May not be
|
||||
combined with any other options or arguments.
|
||||
Print the SHA1, type, and size of each object provided on stdin. May not
|
||||
be combined with any other options or arguments.
|
||||
|
||||
OUTPUT
|
||||
------
|
||||
|
@ -14,7 +14,7 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
For every pathname, this command will list if each attr is 'unspecified',
|
||||
For every pathname, this command will list if each attribute is 'unspecified',
|
||||
'set', or 'unset' as a gitattribute on that pathname.
|
||||
|
||||
OPTIONS
|
||||
@ -23,11 +23,11 @@ OPTIONS
|
||||
Read file names from stdin instead of from the command-line.
|
||||
|
||||
-z::
|
||||
Only meaningful with `--stdin`; paths are separated with
|
||||
NUL character instead of LF.
|
||||
Only meaningful with `--stdin`; paths are separated with a
|
||||
NUL character instead of a linefeed character.
|
||||
|
||||
\--::
|
||||
Interpret all preceding arguments as attributes, and all following
|
||||
Interpret all preceding arguments as attributes and all following
|
||||
arguments as path names. If not supplied, only the first argument will
|
||||
be treated as an attribute.
|
||||
|
||||
@ -37,12 +37,12 @@ OUTPUT
|
||||
The output is of the form:
|
||||
<path> COLON SP <attribute> COLON SP <info> LF
|
||||
|
||||
Where <path> is the path of a file being queried, <attribute> is an attribute
|
||||
<path> is the path of a file being queried, <attribute> is an attribute
|
||||
being queried and <info> can be either:
|
||||
|
||||
'unspecified';; when the attribute is not defined for the path.
|
||||
'unset';; when the attribute is defined to false.
|
||||
'set';; when the attribute is defined to true.
|
||||
'unset';; when the attribute is defined as false.
|
||||
'set';; when the attribute is defined as true.
|
||||
<value>;; when a value has been assigned to the attribute.
|
||||
|
||||
EXAMPLES
|
||||
@ -69,7 +69,7 @@ org/example/MyClass.java: diff: java
|
||||
org/example/MyClass.java: myAttr: set
|
||||
---------------
|
||||
|
||||
* Listing attribute for multiple files:
|
||||
* Listing an attribute for multiple files:
|
||||
---------------
|
||||
$ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java
|
||||
org/example/MyClass.java: myAttr: set
|
||||
|
@ -3,52 +3,70 @@ git-check-ref-format(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-check-ref-format - Make sure ref name is well formed
|
||||
git-check-ref-format - Ensures that a reference name is well formed
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git check-ref-format' <refname>
|
||||
'git check-ref-format' [--branch] <branchname-shorthand>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Checks if a given 'refname' is acceptable, and exits non-zero if
|
||||
it is not.
|
||||
Checks if a given 'refname' is acceptable, and exits with a non-zero
|
||||
status if it is not.
|
||||
|
||||
A reference is used in git to specify branches and tags. A
|
||||
branch head is stored under `$GIT_DIR/refs/heads` directory, and
|
||||
a tag is stored under `$GIT_DIR/refs/tags` directory. git
|
||||
imposes the following rules on how refs are named:
|
||||
branch head is stored under the `$GIT_DIR/refs/heads` directory, and
|
||||
a tag is stored under the `$GIT_DIR/refs/tags` directory. git
|
||||
imposes the following rules on how references are named:
|
||||
|
||||
. It can include slash `/` for hierarchical (directory)
|
||||
. They can include slash `/` for hierarchical (directory)
|
||||
grouping, but no slash-separated component can begin with a
|
||||
dot `.`;
|
||||
dot `.`.
|
||||
|
||||
. It cannot have two consecutive dots `..` anywhere;
|
||||
. They cannot have two consecutive dots `..` anywhere.
|
||||
|
||||
. It cannot have ASCII control character (i.e. bytes whose
|
||||
. They cannot have ASCII control characters (i.e. bytes whose
|
||||
values are lower than \040, or \177 `DEL`), space, tilde `~`,
|
||||
caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`,
|
||||
or open bracket `[` anywhere;
|
||||
or open bracket `[` anywhere.
|
||||
|
||||
. It cannot end with a slash `/`.
|
||||
. They cannot end with a slash `/` nor a dot `.`.
|
||||
|
||||
These rules makes it easy for shell script based tools to parse
|
||||
refnames, pathname expansion by the shell when a refname is used
|
||||
. They cannot end with the sequence `.lock`.
|
||||
|
||||
. They cannot contain a sequence `@{`.
|
||||
|
||||
These rules make it easy for shell script based tools to parse
|
||||
reference names, pathname expansion by the shell when a reference name is used
|
||||
unquoted (by mistake), and also avoids ambiguities in certain
|
||||
refname expressions (see linkgit:git-rev-parse[1]). Namely:
|
||||
reference name expressions (see linkgit:git-rev-parse[1]):
|
||||
|
||||
. double-dot `..` are often used as in `ref1..ref2`, and in some
|
||||
context this notation means `{caret}ref1 ref2` (i.e. not in
|
||||
ref1 and in ref2).
|
||||
. A double-dot `..` is often used as in `ref1..ref2`, and in some
|
||||
contexts this notation means `{caret}ref1 ref2` (i.e. not in
|
||||
`ref1` and in `ref2`).
|
||||
|
||||
. tilde `~` and caret `{caret}` are used to introduce postfix
|
||||
. A tilde `~` and caret `{caret}` are used to introduce the postfix
|
||||
'nth parent' and 'peel onion' operation.
|
||||
|
||||
. colon `:` is used as in `srcref:dstref` to mean "use srcref\'s
|
||||
. A colon `:` is used as in `srcref:dstref` to mean "use srcref\'s
|
||||
value and store it in dstref" in fetch and push operations.
|
||||
It may also be used to select a specific object such as with
|
||||
'git-cat-file': "git cat-file blob v1.3.3:refs.c".
|
||||
|
||||
. at-open-brace `@{` is used as a notation to access a reflog entry.
|
||||
|
||||
With the `--branch` option, it expands a branch name shorthand and
|
||||
prints the name of the branch the shorthand refers to.
|
||||
|
||||
EXAMPLE
|
||||
-------
|
||||
|
||||
git check-ref-format --branch @{-1}::
|
||||
|
||||
Print the name of the previous branch.
|
||||
|
||||
|
||||
GIT
|
||||
---
|
||||
|
@ -8,7 +8,7 @@ git-checkout - Checkout a branch or paths to the working tree
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git checkout' [-q] [-f] [--track | --no-track] [-b <new_branch> [-l]] [-m] [<branch>]
|
||||
'git checkout' [-q] [-f] [-t | --track | --no-track] [-b <new_branch> [-l]] [-m] [<branch>]
|
||||
'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...
|
||||
|
||||
DESCRIPTION
|
||||
@ -21,15 +21,15 @@ specified, <new_branch>. Using -b will cause <new_branch> to
|
||||
be created; in this case you can use the --track or --no-track
|
||||
options, which will be passed to `git branch`.
|
||||
|
||||
As a convenience, --track will default to create a branch whose
|
||||
As a convenience, --track will default to creating a branch whose
|
||||
name is constructed from the specified branch name by stripping
|
||||
the first namespace level.
|
||||
|
||||
When <paths> are given, this command does *not* switch
|
||||
branches. It updates the named paths in the working tree from
|
||||
the index file, or from a named <tree-ish> (most often a commit). In
|
||||
this case, the `-b` options is meaningless and giving
|
||||
either of them results in an error. <tree-ish> argument can be
|
||||
this case, the `-b` and `--track` options are meaningless and giving
|
||||
either of them results in an error. The <tree-ish> argument can be
|
||||
used to specify a specific tree-ish (i.e. commit, tag or tree)
|
||||
to update the index for the given paths before updating the
|
||||
working tree.
|
||||
@ -75,14 +75,13 @@ entries; instead, unmerged entries are ignored.
|
||||
<repository> <refspec>" explicitly. This behavior is the default
|
||||
when the start point is a remote branch. Set the
|
||||
branch.autosetupmerge configuration variable to `false` if you want
|
||||
'git-checkout' and 'git-branch' to always behave as if '--no-track' were
|
||||
'git checkout' and 'git branch' to always behave as if '--no-track' were
|
||||
given. Set it to `always` if you want this behavior when the
|
||||
start-point is either a local or remote branch.
|
||||
start point is either a local or remote branch.
|
||||
+
|
||||
If no '-b' option was given, the name of the new branch will be
|
||||
derived from the remote branch, by attempting to guess the name
|
||||
of the branch on remote system. If "remotes/" or "refs/remotes/"
|
||||
are prefixed, it is stripped away, and then the part up to the
|
||||
If no '-b' option is given, the name of the new branch will be
|
||||
derived from the remote branch. If "remotes/" or "refs/remotes/"
|
||||
is prefixed it is stripped away, and then the part up to the
|
||||
next slash (which would be the nickname of the remote) is removed.
|
||||
This would tell us to use "hack" as the local branch when branching
|
||||
off of "origin/hack" (or "remotes/origin/hack", or even
|
||||
@ -127,16 +126,20 @@ the conflicted merge in the specified paths.
|
||||
<new_branch>::
|
||||
Name for the new branch.
|
||||
|
||||
<tree-ish>::
|
||||
Tree to checkout from (when paths are given). If not specified,
|
||||
the index will be used.
|
||||
|
||||
<branch>::
|
||||
Branch to checkout; may be any object ID that resolves to a
|
||||
commit. Defaults to HEAD.
|
||||
Branch to checkout (when no paths are given); may be any object
|
||||
ID that resolves to a commit. Defaults to HEAD.
|
||||
+
|
||||
When this parameter names a non-branch (but still a valid commit object),
|
||||
your HEAD becomes 'detached'.
|
||||
+
|
||||
As a special case, the "`@\{-N\}`" syntax for the N-th last branch
|
||||
As a special case, the `"@\{-N\}"` syntax for the N-th last branch
|
||||
checks out the branch (instead of detaching). You may also specify
|
||||
"`-`" which is synonymous with "`@\{-1\}`".
|
||||
`-` which is synonymous with `"@\{-1\}"`.
|
||||
|
||||
|
||||
Detached HEAD
|
||||
@ -152,12 +155,12 @@ $ git checkout v2.6.18
|
||||
------------
|
||||
|
||||
Earlier versions of git did not allow this and asked you to
|
||||
create a temporary branch using `-b` option, but starting from
|
||||
create a temporary branch using the `-b` option, but starting from
|
||||
version 1.5.0, the above command 'detaches' your HEAD from the
|
||||
current branch and directly point at the commit named by the tag
|
||||
(`v2.6.18` in the above example).
|
||||
current branch and directly points at the commit named by the tag
|
||||
(`v2.6.18` in the example above).
|
||||
|
||||
You can use usual git commands while in this state. You can use
|
||||
You can use all git commands while in this state. You can use
|
||||
`git reset --hard $othercommit` to further move around, for
|
||||
example. You can make changes and create a new commit on top of
|
||||
a detached HEAD. You can even create a merge by using `git
|
||||
@ -191,8 +194,8 @@ $ git checkout hello.c <3>
|
||||
------------
|
||||
+
|
||||
<1> switch branch
|
||||
<2> take out a file out of other commit
|
||||
<3> restore hello.c from HEAD of current branch
|
||||
<2> take a file out of another commit
|
||||
<3> restore hello.c from the index
|
||||
+
|
||||
If you have an unfortunate branch that is named `hello.c`, this
|
||||
step would be confused as an instruction to switch to that branch.
|
||||
@ -202,7 +205,7 @@ You should instead write:
|
||||
$ git checkout -- hello.c
|
||||
------------
|
||||
|
||||
. After working in a wrong branch, switching to the correct
|
||||
. After working in the wrong branch, switching to the correct
|
||||
branch would be done using:
|
||||
+
|
||||
------------
|
||||
@ -210,7 +213,7 @@ $ git checkout mytopic
|
||||
------------
|
||||
+
|
||||
However, your "wrong" branch and correct "mytopic" branch may
|
||||
differ in files that you have locally modified, in which case,
|
||||
differ in files that you have modified locally, in which case
|
||||
the above checkout would fail like this:
|
||||
+
|
||||
------------
|
||||
|
@ -117,7 +117,7 @@ then the cloned repository will become corrupt.
|
||||
--origin <name>::
|
||||
-o <name>::
|
||||
Instead of using the remote name 'origin' to keep track
|
||||
of the upstream repository, use <name> instead.
|
||||
of the upstream repository, use <name>.
|
||||
|
||||
--upload-pack <upload-pack>::
|
||||
-u <upload-pack>::
|
||||
|
@ -11,7 +11,7 @@ SYNOPSIS
|
||||
[verse]
|
||||
'git config' [<file-option>] [type] [-z|--null] name [value [value_regex]]
|
||||
'git config' [<file-option>] [type] --add name value
|
||||
'git config' [<file-option>] [type] --replace-all name [value [value_regex]]
|
||||
'git config' [<file-option>] [type] --replace-all name value [value_regex]
|
||||
'git config' [<file-option>] [type] [-z|--null] --get name [value_regex]
|
||||
'git config' [<file-option>] [type] [-z|--null] --get-all name [value_regex]
|
||||
'git config' [<file-option>] [type] [-z|--null] --get-regexp name_regex [value_regex]
|
||||
@ -22,6 +22,7 @@ SYNOPSIS
|
||||
'git config' [<file-option>] [-z|--null] -l | --list
|
||||
'git config' [<file-option>] --get-color name [default]
|
||||
'git config' [<file-option>] --get-colorbool name [stdout-is-tty]
|
||||
'git config' [<file-option>] -e | --edit
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -161,6 +162,11 @@ See also <<FILES>>.
|
||||
output. The optional `default` parameter is used instead, if
|
||||
there is no color configured for `name`.
|
||||
|
||||
-e::
|
||||
--edit::
|
||||
Opens an editor to modify the specified config file; either
|
||||
'--system', '--global', or repository (default).
|
||||
|
||||
[[FILES]]
|
||||
FILES
|
||||
-----
|
||||
|
@ -24,6 +24,9 @@ repository, or incrementally import into an existing one.
|
||||
Splitting the CVS log into patch sets is done by 'cvsps'.
|
||||
At least version 2.1 is required.
|
||||
|
||||
*WARNING:* for certain situations the import leads to incorrect results.
|
||||
Please see the section <<issues,ISSUES>> for further reference.
|
||||
|
||||
You should *never* do any work of your own on the branches that are
|
||||
created by 'git-cvsimport'. By default initial import will create and populate a
|
||||
"master" branch from the CVS repository's main branch which you're free
|
||||
@ -62,7 +65,7 @@ OPTIONS
|
||||
-r <remote>::
|
||||
The git remote to import this CVS repository into.
|
||||
Moves all CVS branches into remotes/<remote>/<branch>
|
||||
akin to the 'git-clone' "--use-separate-remote" option.
|
||||
akin to the way 'git-clone' uses 'origin' by default.
|
||||
|
||||
-o <branch-for-HEAD>::
|
||||
When no remote is specified (via -r) the 'HEAD' branch
|
||||
@ -164,6 +167,39 @@ If '-v' is specified, the script reports what it is doing.
|
||||
Otherwise, success is indicated the Unix way, i.e. by simply exiting with
|
||||
a zero exit status.
|
||||
|
||||
[[issues]]
|
||||
ISSUES
|
||||
------
|
||||
Problems related to timestamps:
|
||||
|
||||
* If timestamps of commits in the cvs repository are not stable enough
|
||||
to be used for ordering commits changes may show up in the wrong
|
||||
order.
|
||||
* If any files were ever "cvs import"ed more than once (e.g., import of
|
||||
more than one vendor release) the HEAD contains the wrong content.
|
||||
* If the timestamp order of different files cross the revision order
|
||||
within the commit matching time window the order of commits may be
|
||||
wrong.
|
||||
|
||||
Problems related to branches:
|
||||
|
||||
* Branches on which no commits have been made are not imported.
|
||||
* All files from the branching point are added to a branch even if
|
||||
never added in cvs.
|
||||
* This applies to files added to the source branch *after* a daughter
|
||||
branch was created: if previously no commit was made on the daughter
|
||||
branch they will erroneously be added to the daughter branch in git.
|
||||
|
||||
Problems related to tags:
|
||||
|
||||
* Multiple tags on the same revision are not imported.
|
||||
|
||||
If you suspect that any of these issues may apply to the repository you
|
||||
want to import consider using these alternative tools which proved to be
|
||||
more stable in practise:
|
||||
|
||||
* cvs2git (part of cvs2svn), `http://cvs2svn.tigris.org`
|
||||
* parsecvs, `http://cgit.freedesktop.org/~keithp/parsecvs`
|
||||
|
||||
Author
|
||||
------
|
||||
|
@ -31,6 +31,9 @@ changes, which would normally have no effect. Nevertheless, this may be
|
||||
useful in the future for compensating for some git bugs or such,
|
||||
therefore such a usage is permitted.
|
||||
|
||||
*NOTE*: This command honors `.git/info/grafts`. If you have any grafts
|
||||
defined, running this command will make them permanent.
|
||||
|
||||
*WARNING*! The rewritten history will have different object names for all
|
||||
the objects and will not converge with the original branch. You will not
|
||||
be able to easily push and distribute the rewritten branch on top of the
|
||||
@ -91,7 +94,9 @@ OPTIONS
|
||||
--index-filter <command>::
|
||||
This is the filter for rewriting the index. It is similar to the
|
||||
tree filter but does not check out the tree, which makes it much
|
||||
faster. For hairy cases, see linkgit:git-update-index[1].
|
||||
faster. Frequently used with `git rm \--cached
|
||||
\--ignore-unmatch ...`, see EXAMPLES below. For hairy
|
||||
cases, see linkgit:git-update-index[1].
|
||||
|
||||
--parent-filter <command>::
|
||||
This is the filter for rewriting the commit's parent list.
|
||||
@ -204,19 +209,18 @@ However, if the file is absent from the tree of some commit,
|
||||
a simple `rm filename` will fail for that tree and commit.
|
||||
Thus you may instead want to use `rm -f filename` as the script.
|
||||
|
||||
A significantly faster version:
|
||||
Using `\--index-filter` with 'git-rm' yields a significantly faster
|
||||
version. Like with using `rm filename`, `git rm --cached filename`
|
||||
will fail if the file is absent from the tree of a commit. If you
|
||||
want to "completely forget" a file, it does not matter when it entered
|
||||
history, so we also add `\--ignore-unmatch`:
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
git filter-branch --index-filter 'git rm --cached filename' HEAD
|
||||
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
Now, you will get the rewritten history saved in HEAD.
|
||||
|
||||
As with using `rm filename`, `git rm --cached filename` will fail
|
||||
if the file is absent from the tree of a commit. If it is not important
|
||||
whether the file is already absent from the tree, you can use
|
||||
`git rm --cached --ignore-unmatch filename` instead.
|
||||
|
||||
To rewrite the repository to look as if `foodir/` had been its project
|
||||
root, and discard all other history:
|
||||
|
||||
|
@ -85,6 +85,11 @@ objectsize::
|
||||
objectname::
|
||||
The object name (aka SHA-1).
|
||||
|
||||
upstream::
|
||||
The name of a local ref which can be considered ``upstream''
|
||||
from the displayed ref. Respects `:short` in the same way as
|
||||
`refname` above.
|
||||
|
||||
In addition to the above, for commit and tag objects, the header
|
||||
field names (`tree`, `parent`, `object`, `type`, and `tag`) can
|
||||
be used to specify the value in the header field.
|
||||
|
@ -10,7 +10,8 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git format-patch' [-k] [-o <dir> | --stdout] [--thread]
|
||||
[--attach[=<boundary>] | --inline[=<boundary>]]
|
||||
[--attach[=<boundary>] | --inline[=<boundary>] |
|
||||
[--no-attach]]
|
||||
[-s | --signoff] [<common diff options>]
|
||||
[-n | --numbered | -N | --no-numbered]
|
||||
[--start-number <n>] [--numbered-files]
|
||||
@ -39,15 +40,11 @@ There are two ways to specify which commits to operate on.
|
||||
REVISIONS" section in linkgit:git-rev-parse[1]) means the
|
||||
commits in the specified range.
|
||||
|
||||
A single commit, when interpreted as a <revision range>
|
||||
expression, means "everything that leads to that commit", but
|
||||
if you write 'git format-patch <commit>', the previous rule
|
||||
applies to that command line and you do not get "everything
|
||||
since the beginning of the time". If you want to format
|
||||
everything since project inception to one commit, say "git
|
||||
format-patch \--root <commit>" to make it clear that it is the
|
||||
latter case. If you want to format a single commit, you can do
|
||||
this with "git format-patch -1 <commit>".
|
||||
The first rule takes precedence in the case of a single <commit>. To
|
||||
apply the second rule, i.e., format everything since the beginning of
|
||||
history up until <commit>, use the '\--root' option: "git format-patch
|
||||
\--root <commit>". If you want to format only <commit> itself, you
|
||||
can do this with "git format-patch -1 <commit>".
|
||||
|
||||
By default, each output file is numbered sequentially from 1, and uses the
|
||||
first line of the commit message (massaged for pathname safety) as
|
||||
@ -116,15 +113,27 @@ include::diff-options.txt[]
|
||||
which is the commit message and the patch itself in the
|
||||
second part, with "Content-Disposition: attachment".
|
||||
|
||||
--no-attach::
|
||||
Disable the creation of an attachment, overriding the
|
||||
configuration setting.
|
||||
|
||||
--inline[=<boundary>]::
|
||||
Create multipart/mixed attachment, the first part of
|
||||
which is the commit message and the patch itself in the
|
||||
second part, with "Content-Disposition: inline".
|
||||
|
||||
--thread::
|
||||
--thread[=<style>]::
|
||||
Add In-Reply-To and References headers to make the second and
|
||||
subsequent mails appear as replies to the first. Also generates
|
||||
the Message-Id header to reference.
|
||||
+
|
||||
The optional <style> argument can be either `shallow` or `deep`.
|
||||
'Shallow' threading makes every mail a reply to the head of the
|
||||
series, where the head is chosen from the cover letter, the
|
||||
`\--in-reply-to`, and the first patch mail, in this order. 'Deep'
|
||||
threading makes every mail a reply to the previous one. If not
|
||||
specified, defaults to the 'format.thread' configuration, or `shallow`
|
||||
if that is not set.
|
||||
|
||||
--in-reply-to=Message-Id::
|
||||
Make the first mail (or all the mails with --no-thread) appear as a
|
||||
@ -148,6 +157,11 @@ include::diff-options.txt[]
|
||||
Add a "Cc:" header to the email headers. This is in addition
|
||||
to any configured headers, and may be used multiple times.
|
||||
|
||||
--add-header=<header>::
|
||||
Add an arbitrary header to the email headers. This is in addition
|
||||
to any configured headers, and may be used multiple times.
|
||||
For example, --add-header="Organization: git-foo"
|
||||
|
||||
--cover-letter::
|
||||
In addition to the patches, generate a cover letter file
|
||||
containing the shortlog and the overall diffstat. You can
|
||||
@ -169,11 +183,19 @@ not add any suffix.
|
||||
applied. By default the contents of changes in those files are
|
||||
encoded in the patch.
|
||||
|
||||
--root::
|
||||
Treat the revision argument as a <revision range>, even if it
|
||||
is just a single commit (that would normally be treated as a
|
||||
<since>). Note that root commits included in the specified
|
||||
range are always formatted as creation patches, independently
|
||||
of this flag.
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
You can specify extra mail header lines to be added to each message
|
||||
in the repository configuration, new defaults for the subject prefix
|
||||
and file suffix, and number patches when outputting more than one.
|
||||
and file suffix, control attachements, and number patches when outputting
|
||||
more than one.
|
||||
|
||||
------------
|
||||
[format]
|
||||
@ -182,6 +204,8 @@ and file suffix, and number patches when outputting more than one.
|
||||
suffix = .txt
|
||||
numbered = auto
|
||||
cc = <email>
|
||||
attach [ = mime-boundary-string ]
|
||||
signoff = true
|
||||
------------
|
||||
|
||||
|
||||
|
@ -17,6 +17,7 @@ SYNOPSIS
|
||||
[-l | --files-with-matches] [-L | --files-without-match]
|
||||
[-z | --null]
|
||||
[-c | --count] [--all-match]
|
||||
[--color | --no-color]
|
||||
[-A <post-context>] [-B <pre-context>] [-C <context>]
|
||||
[-f <file>] [-e] <pattern>
|
||||
[--and|--or|--not|(|)|-e <pattern>...] [<tree>...]
|
||||
@ -105,6 +106,13 @@ OPTIONS
|
||||
Instead of showing every matched line, show the number of
|
||||
lines that match.
|
||||
|
||||
--color::
|
||||
Show colored matches.
|
||||
|
||||
--no-color::
|
||||
Turn off match highlighting, even when the configuration file
|
||||
gives the default to color output.
|
||||
|
||||
-[ABC] <context>::
|
||||
Show `context` trailing (`A` -- after), or leading (`B`
|
||||
-- before), or both (`C` -- context) lines, and place a
|
||||
|
@ -64,6 +64,13 @@ imap.sslverify::
|
||||
used by the SSL/TLS connection. Default is `true`. Ignored when
|
||||
imap.tunnel is set.
|
||||
|
||||
imap.preformattedHTML::
|
||||
A boolean to enable/disable the use of html encoding when sending
|
||||
a patch. An html encoded patch will be bracketed with <pre>
|
||||
and have a content type of text/html. Ironically, enabling this
|
||||
option causes Thunderbird to send the patch as a plain/text,
|
||||
format=fixed email. Default is `false`.
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
|
||||
|
@ -40,8 +40,8 @@ include::merge-options.txt[]
|
||||
include::merge-strategies.txt[]
|
||||
|
||||
|
||||
If you tried a merge which resulted in a complex conflicts and
|
||||
would want to start over, you can recover with 'git-reset'.
|
||||
If you tried a merge which resulted in complex conflicts and
|
||||
want to start over, you can recover with 'git-reset'.
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
@ -146,7 +146,7 @@ And here is another line that is cleanly resolved or unmodified.
|
||||
------------
|
||||
|
||||
The area where a pair of conflicting changes happened is marked with markers
|
||||
"`<<<<<<<`", "`=======`", and "`>>>>>>>`". The part before the "`=======`"
|
||||
`<<<<<<<`, `=======`, and `>>>>>>>`. The part before the `=======`
|
||||
is typically your side, and the part afterwards is typically their side.
|
||||
|
||||
The default format does not show what the original said in the conflicting
|
||||
@ -173,8 +173,8 @@ Git makes conflict resolution easy.
|
||||
And here is another line that is cleanly resolved or unmodified.
|
||||
------------
|
||||
|
||||
In addition to the "`<<<<<<<`", "`=======`", and "`>>>>>>>`" markers, it uses
|
||||
another "`|||||||`" marker that is followed by the original text. You can
|
||||
In addition to the `<<<<<<<`, `=======`, and `>>>>>>>` markers, it uses
|
||||
another `|||||||` marker that is followed by the original text. You can
|
||||
tell that the original just stated a fact, and your side simply gave in to
|
||||
that statement and gave up, while the other side tried to have a more
|
||||
positive attitude. You can sometimes come up with a better resolution by
|
||||
|
@ -26,7 +26,7 @@ problem by stashing the refs in a single file,
|
||||
traditional `$GIT_DIR/refs` hierarchy, it is looked up in this
|
||||
file and used if found.
|
||||
|
||||
Subsequent updates to branches always creates new file under
|
||||
Subsequent updates to branches always create new files under
|
||||
`$GIT_DIR/refs` hierarchy.
|
||||
|
||||
A recommended practice to deal with a repository with too many
|
||||
@ -35,7 +35,7 @@ occasionally run `git pack-refs \--prune`. Tags are by
|
||||
definition stationary and are not expected to change. Branch
|
||||
heads will be packed with the initial `pack-refs --all`, but
|
||||
only the currently active branch heads will become unpacked,
|
||||
and next `pack-refs` (without `--all`) will leave them
|
||||
and the next `pack-refs` (without `--all`) will leave them
|
||||
unpacked.
|
||||
|
||||
|
||||
|
@ -20,7 +20,7 @@ IOW, you can use this thing to look for likely duplicate commits.
|
||||
|
||||
When dealing with 'git-diff-tree' output, it takes advantage of
|
||||
the fact that the patch is prefixed with the object name of the
|
||||
commit, and outputs two 40-byte hexadecimal string. The first
|
||||
commit, and outputs two 40-byte hexadecimal strings. The first
|
||||
string is the patch ID, and the second string is the commit ID.
|
||||
This can be used to make a mapping from patch ID to commit ID.
|
||||
|
||||
|
@ -24,8 +24,8 @@ every time you push into it, by setting up 'hooks' there. See
|
||||
documentation for linkgit:git-receive-pack[1].
|
||||
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
OPTIONS[[OPTIONS]]
|
||||
------------------
|
||||
<repository>::
|
||||
The "remote" repository that is destination of a push
|
||||
operation. This parameter can be either a URL
|
||||
@ -187,6 +187,28 @@ reason::
|
||||
Examples
|
||||
--------
|
||||
|
||||
git push::
|
||||
Works like `git push <remote>`, where <remote> is the
|
||||
current branch's remote (or `origin`, if no remote is
|
||||
configured for the current branch).
|
||||
|
||||
git push origin::
|
||||
Without additional configuration, works like
|
||||
`git push origin :`.
|
||||
+
|
||||
The default behavior of this command when no <refspec> is given can be
|
||||
configured by setting the `push` option of the remote.
|
||||
+
|
||||
For example, to default to pushing only the current branch to `origin`
|
||||
use `git config remote.origin.push HEAD`. Any valid <refspec> (like
|
||||
the ones in the examples below) can be configured as the default for
|
||||
`git push origin`.
|
||||
|
||||
git push origin :::
|
||||
Push "matching" branches to `origin`. See
|
||||
<refspec> in the <<OPTIONS,OPTIONS>> section above for a
|
||||
description of "matching" branches.
|
||||
|
||||
git push origin master::
|
||||
Find a ref that matches `master` in the source repository
|
||||
(most likely, it would find `refs/heads/master`), and update
|
||||
|
@ -192,6 +192,13 @@ Alternatively, you can undo the 'git-rebase' with
|
||||
|
||||
git rebase --abort
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
|
||||
rebase.stat::
|
||||
Whether to show a diffstat of what changed upstream since the last
|
||||
rebase. False by default.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
<newbase>::
|
||||
@ -232,7 +239,15 @@ OPTIONS
|
||||
|
||||
-v::
|
||||
--verbose::
|
||||
Display a diffstat of what changed upstream since the last rebase.
|
||||
Be verbose. Implies --stat.
|
||||
|
||||
--stat::
|
||||
Show a diffstat of what changed upstream since the last rebase. The
|
||||
diffstat is also controlled by the configuration option rebase.stat.
|
||||
|
||||
-n::
|
||||
--no-stat::
|
||||
Do not show a diffstat as part of the rebase process.
|
||||
|
||||
--no-verify::
|
||||
This option bypasses the pre-rebase hook. See also linkgit:githooks[5].
|
||||
@ -243,11 +258,23 @@ OPTIONS
|
||||
context exist they all must match. By default no context is
|
||||
ever ignored.
|
||||
|
||||
-f::
|
||||
--force-rebase::
|
||||
Force the rebase even if the current branch is a descendant
|
||||
of the commit you are rebasing onto. Normally the command will
|
||||
exit with the message "Current branch is up to date" in such a
|
||||
situation.
|
||||
|
||||
--whitespace=<option>::
|
||||
This flag is passed to the 'git-apply' program
|
||||
(see linkgit:git-apply[1]) that applies the patch.
|
||||
Incompatible with the --interactive option.
|
||||
|
||||
--committer-date-is-author-date::
|
||||
--ignore-date::
|
||||
These flags are passed to 'git-am' to easily change the dates
|
||||
of the rebased commits (see linkgit:git-am[1]).
|
||||
|
||||
-i::
|
||||
--interactive::
|
||||
Make a list of the commits which are about to be rebased. Let the
|
||||
|
@ -13,9 +13,10 @@ SYNOPSIS
|
||||
'git remote add' [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>
|
||||
'git remote rename' <old> <new>
|
||||
'git remote rm' <name>
|
||||
'git remote set-head' <name> [-a | -d | <branch>]
|
||||
'git remote show' [-n] <name>
|
||||
'git remote prune' [-n | --dry-run] <name>
|
||||
'git remote update' [group]
|
||||
'git remote update' [-p | --prune] [group | remote]...
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -53,8 +54,7 @@ is created. You can give more than one `-t <branch>` to track
|
||||
multiple branches without grabbing all branches.
|
||||
+
|
||||
With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
|
||||
up to point at remote's `<master>` branch instead of whatever
|
||||
branch the `HEAD` at the remote repository actually points at.
|
||||
up to point at remote's `<master>` branch. See also the set-head command.
|
||||
+
|
||||
In mirror mode, enabled with `\--mirror`, the refs will not be stored
|
||||
in the 'refs/remotes/' namespace, but in 'refs/heads/'. This option
|
||||
@ -76,6 +76,30 @@ the configuration file format.
|
||||
Remove the remote named <name>. All remote tracking branches and
|
||||
configuration settings for the remote are removed.
|
||||
|
||||
'set-head'::
|
||||
|
||||
Sets or deletes the default branch (`$GIT_DIR/remotes/<name>/HEAD`) for
|
||||
the named remote. Having a default branch for a remote is not required,
|
||||
but allows the name of the remote to be specified in lieu of a specific
|
||||
branch. For example, if the default branch for `origin` is set to
|
||||
`master`, then `origin` may be specified wherever you would normally
|
||||
specify `origin/master`.
|
||||
+
|
||||
With `-d`, `$GIT_DIR/remotes/<name>/HEAD` is deleted.
|
||||
+
|
||||
With `-a`, the remote is queried to determine its `HEAD`, then
|
||||
`$GIT_DIR/remotes/<name>/HEAD` is set to the same branch. e.g., if the remote
|
||||
`HEAD` is pointed at `next`, "`git remote set-head origin -a`" will set
|
||||
`$GIT_DIR/refs/remotes/origin/HEAD` to `refs/remotes/origin/next`. This will
|
||||
only work if `refs/remotes/origin/next` already exists; if not it must be
|
||||
fetched first.
|
||||
+
|
||||
Use `<branch>` to set `$GIT_DIR/remotes/<name>/HEAD` explicitly. e.g., "git
|
||||
remote set-head origin master" will set `$GIT_DIR/refs/remotes/origin/HEAD` to
|
||||
`refs/remotes/origin/master`. This will only work if
|
||||
`refs/remotes/origin/master` already exists; if not it must be fetched first.
|
||||
+
|
||||
|
||||
'show'::
|
||||
|
||||
Gives some information about the remote <name>.
|
||||
@ -101,6 +125,8 @@ the configuration parameter remotes.default will get used; if
|
||||
remotes.default is not defined, all remotes which do not have the
|
||||
configuration parameter remote.<name>.skipDefaultUpdate set to true will
|
||||
be updated. (See linkgit:git-config[1]).
|
||||
+
|
||||
With `--prune` option, prune all the remotes that are updated.
|
||||
|
||||
|
||||
DISCUSSION
|
||||
|
@ -299,18 +299,18 @@ previous section means the set of commits reachable from that
|
||||
commit, following the commit ancestry chain.
|
||||
|
||||
To exclude commits reachable from a commit, a prefix `{caret}`
|
||||
notation is used. E.g. "`{caret}r1 r2`" means commits reachable
|
||||
notation is used. E.g. `{caret}r1 r2` means commits reachable
|
||||
from `r2` but exclude the ones reachable from `r1`.
|
||||
|
||||
This set operation appears so often that there is a shorthand
|
||||
for it. When you have two commits `r1` and `r2` (named according
|
||||
to the syntax explained in SPECIFYING REVISIONS above), you can ask
|
||||
for commits that are reachable from r2 excluding those that are reachable
|
||||
from r1 by "`{caret}r1 r2`" and it can be written as "`r1..r2`".
|
||||
from r1 by `{caret}r1 r2` and it can be written as `r1..r2`.
|
||||
|
||||
A similar notation "`r1\...r2`" is called symmetric difference
|
||||
A similar notation `r1\...r2` is called symmetric difference
|
||||
of `r1` and `r2` and is defined as
|
||||
"`r1 r2 --not $(git merge-base --all r1 r2)`".
|
||||
`r1 r2 --not $(git merge-base --all r1 r2)`.
|
||||
It is the set of commits that are reachable from either one of
|
||||
`r1` or `r2` but not from both.
|
||||
|
||||
|
@ -39,13 +39,13 @@ OPTIONS
|
||||
Composing
|
||||
~~~~~~~~~
|
||||
|
||||
--bcc::
|
||||
--bcc=<address>::
|
||||
Specify a "Bcc:" value for each email. Default is the value of
|
||||
'sendemail.bcc'.
|
||||
+
|
||||
The --bcc option must be repeated for each user you want on the bcc list.
|
||||
|
||||
--cc::
|
||||
--cc=<address>::
|
||||
Specify a starting "Cc:" value for each email.
|
||||
Default is the value of 'sendemail.cc'.
|
||||
+
|
||||
@ -60,33 +60,32 @@ The --cc option must be repeated for each user you want on the cc list.
|
||||
Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an
|
||||
introductory message for the patch series.
|
||||
+
|
||||
When '--compose' is used, git send-email gets less interactive will use the
|
||||
values of the headers you set there. If the body of the email (what you type
|
||||
after the headers and a blank line) only contains blank (or GIT: prefixed)
|
||||
lines, the summary won't be sent, but git-send-email will still use the
|
||||
Headers values if you don't removed them.
|
||||
When '--compose' is used, git send-email will use the From, Subject, and
|
||||
In-Reply-To headers specified in the message. If the body of the message
|
||||
(what you type after the headers and a blank line) only contains blank
|
||||
(or GIT: prefixed) lines the summary won't be sent, but From, Subject,
|
||||
and In-Reply-To headers will be used unless they are removed.
|
||||
+
|
||||
If it wasn't able to see a header in the summary it will ask you about it
|
||||
interactively after quitting your editor.
|
||||
Missing From or In-Reply-To headers will be prompted for.
|
||||
|
||||
--from::
|
||||
--from=<address>::
|
||||
Specify the sender of the emails. This will default to
|
||||
the value GIT_COMMITTER_IDENT, as returned by "git var -l".
|
||||
The user will still be prompted to confirm this entry.
|
||||
|
||||
--in-reply-to::
|
||||
--in-reply-to=<identifier>::
|
||||
Specify the contents of the first In-Reply-To header.
|
||||
Subsequent emails will refer to the previous email
|
||||
instead of this if --chain-reply-to is set (the default)
|
||||
Only necessary if --compose is also set. If --compose
|
||||
is not set, this will be prompted for.
|
||||
|
||||
--subject::
|
||||
--subject=<string>::
|
||||
Specify the initial subject of the email thread.
|
||||
Only necessary if --compose is also set. If --compose
|
||||
is not set, this will be prompted for.
|
||||
|
||||
--to::
|
||||
--to=<address>::
|
||||
Specify the primary recipient of the emails generated. Generally, this
|
||||
will be the upstream maintainer of the project involved. Default is the
|
||||
value of the 'sendemail.to' configuration value; if that is unspecified,
|
||||
@ -98,7 +97,7 @@ The --to option must be repeated for each user you want on the to list.
|
||||
Sending
|
||||
~~~~~~~
|
||||
|
||||
--envelope-sender::
|
||||
--envelope-sender=<address>::
|
||||
Specify the envelope sender used to send the emails.
|
||||
This is useful if your default address is not the address that is
|
||||
subscribed to a list. If you use the sendmail binary, you must have
|
||||
@ -106,12 +105,12 @@ Sending
|
||||
the 'sendemail.envelopesender' configuration variable; if that is
|
||||
unspecified, choosing the envelope sender is left to your MTA.
|
||||
|
||||
--smtp-encryption::
|
||||
--smtp-encryption=<encryption>::
|
||||
Specify the encryption to use, either 'ssl' or 'tls'. Any other
|
||||
value reverts to plain SMTP. Default is the value of
|
||||
'sendemail.smtpencryption'.
|
||||
|
||||
--smtp-pass::
|
||||
--smtp-pass[=<password>]::
|
||||
Password for SMTP-AUTH. The argument is optional: If no
|
||||
argument is specified, then the empty string is used as
|
||||
the password. Default is the value of 'sendemail.smtppass',
|
||||
@ -123,7 +122,7 @@ or on the command line. If a username has been specified (with
|
||||
specified (with '--smtp-pass' or 'sendemail.smtppass'), then the
|
||||
user is prompted for a password while the input is masked for privacy.
|
||||
|
||||
--smtp-server::
|
||||
--smtp-server=<host>::
|
||||
If set, specifies the outgoing SMTP server to use (e.g.
|
||||
`smtp.example.com` or a raw IP address). Alternatively it can
|
||||
specify a full pathname of a sendmail-like program instead;
|
||||
@ -133,7 +132,7 @@ user is prompted for a password while the input is masked for privacy.
|
||||
`/usr/lib/sendmail` if such program is available, or
|
||||
`localhost` otherwise.
|
||||
|
||||
--smtp-server-port::
|
||||
--smtp-server-port=<port>::
|
||||
Specifies a port different from the default port (SMTP
|
||||
servers typically listen to smtp port 25 and ssmtp port
|
||||
465). This can be set with 'sendemail.smtpserverport'.
|
||||
@ -141,7 +140,7 @@ user is prompted for a password while the input is masked for privacy.
|
||||
--smtp-ssl::
|
||||
Legacy alias for '--smtp-encryption ssl'.
|
||||
|
||||
--smtp-user::
|
||||
--smtp-user=<user>::
|
||||
Username for SMTP-AUTH. Default is the value of 'sendemail.smtpuser';
|
||||
if a username is not specified (with '--smtp-user' or 'sendemail.smtpuser'),
|
||||
then authentication is not attempted.
|
||||
@ -150,13 +149,13 @@ user is prompted for a password while the input is masked for privacy.
|
||||
Automating
|
||||
~~~~~~~~~~
|
||||
|
||||
--cc-cmd::
|
||||
--cc-cmd=<command>::
|
||||
Specify a command to execute once per patch file which
|
||||
should generate patch file specific "Cc:" entries.
|
||||
Output of this command must be single email address per line.
|
||||
Default is the value of 'sendemail.cccmd' configuration value.
|
||||
|
||||
--[no-]chain-reply-to::
|
||||
--[no-]chain-reply-to=<identifier>::
|
||||
If this is set, each email will be sent as a reply to the previous
|
||||
email sent. If disabled with "--no-chain-reply-to", all emails after
|
||||
the first will be sent as replies to the first email sent. When using
|
||||
@ -164,7 +163,7 @@ Automating
|
||||
entire patch series. Default is the value of the 'sendemail.chainreplyto'
|
||||
configuration value; if that is unspecified, default to --chain-reply-to.
|
||||
|
||||
--identity::
|
||||
--identity=<identity>::
|
||||
A configuration identity. When given, causes values in the
|
||||
'sendemail.<identity>' subsection to take precedence over
|
||||
values in the 'sendemail' section. The default identity is
|
||||
@ -175,7 +174,7 @@ Automating
|
||||
cc list. Default is the value of 'sendemail.signedoffbycc' configuration
|
||||
value; if that is unspecified, default to --signed-off-by-cc.
|
||||
|
||||
--suppress-cc::
|
||||
--suppress-cc=<category>::
|
||||
Specify an additional category of recipients to suppress the
|
||||
auto-cc of:
|
||||
+
|
||||
@ -212,6 +211,22 @@ specified, as well as 'body' if --no-signed-off-cc is specified.
|
||||
Administering
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
--confirm=<mode>::
|
||||
Confirm just before sending:
|
||||
+
|
||||
--
|
||||
- 'always' will always confirm before sending
|
||||
- 'never' will never confirm before sending
|
||||
- 'cc' will confirm before sending when send-email has automatically
|
||||
added addresses from the patch to the Cc list
|
||||
- 'compose' will confirm before sending the first message when using --compose.
|
||||
- 'auto' is equivalent to 'cc' + 'compose'
|
||||
--
|
||||
+
|
||||
Default is the value of 'sendemail.confirm' configuration value; if that
|
||||
is unspecified, default to 'auto' unless any of the suppress options
|
||||
have been specified, in which case default to 'compose'.
|
||||
|
||||
--dry-run::
|
||||
Do everything except actually send the emails.
|
||||
|
||||
@ -255,6 +270,11 @@ sendemail.multiedit::
|
||||
summary when '--compose' is used). If false, files will be edited one
|
||||
after the other, spawning a new editor each time.
|
||||
|
||||
sendemail.confirm::
|
||||
Sets the default for whether to confirm before sending. Must be
|
||||
one of 'always', 'never', 'cc', 'compose', or 'auto'. See '--confirm'
|
||||
in the previous section for the meaning of these values.
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
|
@ -85,6 +85,10 @@ COMMANDS
|
||||
specified, the prefix must include a trailing slash.
|
||||
Setting a prefix is useful if you wish to track multiple
|
||||
projects that share a common repository.
|
||||
--ignore-paths=<regex>;;
|
||||
When passed to 'init' or 'clone' this regular expression will
|
||||
be preserved as a config key. See 'fetch' for a description
|
||||
of '--ignore-paths'.
|
||||
|
||||
'fetch'::
|
||||
Fetch unfetched revisions from the Subversion remote we are
|
||||
@ -97,6 +101,9 @@ COMMANDS
|
||||
makes 'git-log' (even without --date=local) show the same times
|
||||
that `svn log` would in the local timezone.
|
||||
|
||||
--parent;;
|
||||
Fetch only from the SVN parent of the current HEAD.
|
||||
|
||||
This doesn't interfere with interoperating with the Subversion
|
||||
repository you cloned from, but if you wish for your local Git
|
||||
repository to be able to interoperate with someone else's local Git
|
||||
@ -104,17 +111,25 @@ repository, either don't use this option or you should both use it in
|
||||
the same local timezone.
|
||||
|
||||
--ignore-paths=<regex>;;
|
||||
This allows one to specify Perl regular expression that will
|
||||
This allows one to specify a Perl regular expression that will
|
||||
cause skipping of all matching paths from checkout from SVN.
|
||||
Examples:
|
||||
The '--ignore-paths' option should match for every 'fetch'
|
||||
(including automatic fetches due to 'clone', 'dcommit',
|
||||
'rebase', etc) on a given repository.
|
||||
|
||||
--ignore-paths="^doc" - skip "doc*" directory for every fetch.
|
||||
config key: svn-remote.<name>.ignore-paths
|
||||
|
||||
--ignore-paths="^[^/]+/(?:branches|tags)" - skip "branches"
|
||||
and "tags" of first level directories.
|
||||
If the ignore-paths config key is set and the command
|
||||
line option is also given, both regular expressions
|
||||
will be used.
|
||||
|
||||
Regular expression is not persistent, you should specify
|
||||
it every time when fetching.
|
||||
Examples:
|
||||
|
||||
--ignore-paths="^doc" - skip "doc*" directory for every
|
||||
fetch.
|
||||
|
||||
--ignore-paths="^[^/]+/(?:branches|tags)" - skip
|
||||
"branches" and "tags" of first level directories.
|
||||
|
||||
'clone'::
|
||||
Runs 'init' and 'fetch'. It will automatically create a
|
||||
@ -385,7 +400,8 @@ config key: svn.authorsfile
|
||||
|
||||
-q::
|
||||
--quiet::
|
||||
Make 'git-svn' less verbose.
|
||||
Make 'git-svn' less verbose. Specify a second time to make it
|
||||
even less verbose.
|
||||
|
||||
--repack[=<n>]::
|
||||
--repack-flags=<flags>::
|
||||
@ -672,9 +688,9 @@ listed below are allowed:
|
||||
------------------------------------------------------------------------
|
||||
[svn-remote "project-a"]
|
||||
url = http://server.org/svn
|
||||
fetch = trunk/project-a:refs/remotes/project-a/trunk
|
||||
branches = branches/*/project-a:refs/remotes/project-a/branches/*
|
||||
tags = tags/*/project-a:refs/remotes/project-a/tags/*
|
||||
trunk = trunk/project-a:refs/remotes/project-a/trunk
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Keep in mind that the '*' (asterisk) wildcard of the local ref
|
||||
|
@ -63,6 +63,7 @@ OPTIONS
|
||||
are printed when using -l.
|
||||
The default is not to print any annotation lines.
|
||||
If no number is given to `-n`, only the first line is printed.
|
||||
If the tag is not annotated, the commit message is displayed instead.
|
||||
|
||||
-l <pattern>::
|
||||
List tags with names that match the given pattern (or all if no pattern is given).
|
||||
|
@ -9,7 +9,7 @@ git - the stupid content tracker
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git' [--version] [--exec-path[=GIT_EXEC_PATH]]
|
||||
'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]
|
||||
[-p|--paginate|--no-pager]
|
||||
[--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]
|
||||
[--help] COMMAND [ARGS]
|
||||
@ -43,9 +43,12 @@ unreleased) version of git, that is available from 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:v1.6.2/git.html[documentation for release 1.6.2]
|
||||
* link:v1.6.2.3/git.html[documentation for release 1.6.2.3]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes-1.6.2.3.txt[1.6.2.3],
|
||||
link:RelNotes-1.6.2.2.txt[1.6.2.2],
|
||||
link:RelNotes-1.6.2.1.txt[1.6.2.1],
|
||||
link:RelNotes-1.6.2.txt[1.6.2].
|
||||
|
||||
* link:v1.6.1.3/git.html[documentation for release 1.6.1.3]
|
||||
@ -177,6 +180,10 @@ help ...`.
|
||||
environment variable. If no path is given, 'git' will print
|
||||
the current setting and then exit.
|
||||
|
||||
--html-path::
|
||||
Print the path to wherever your git HTML documentation is installed
|
||||
and exit.
|
||||
|
||||
-p::
|
||||
--paginate::
|
||||
Pipe all output into 'less' (or if set, $PAGER).
|
||||
|
@ -60,9 +60,9 @@ same as in `.gitignore` files; see linkgit:gitignore[5].
|
||||
When deciding what attributes are assigned to a path, git
|
||||
consults `$GIT_DIR/info/attributes` file (which has the highest
|
||||
precedence), `.gitattributes` file in the same directory as the
|
||||
path in question, and its parent directories (the further the
|
||||
directory that contains `.gitattributes` is from the path in
|
||||
question, the lower its precedence).
|
||||
path in question, and its parent directories up to the toplevel of the
|
||||
work tree (the further the directory that contains `.gitattributes`
|
||||
is from the path in question, the lower its precedence).
|
||||
|
||||
If you wish to affect only a single repository (i.e., to assign
|
||||
attributes to files that are particular to one user's workflow), then
|
||||
|
@ -46,20 +46,20 @@ Here are the rules regarding the "flags" that you should follow when you are
|
||||
scripting git:
|
||||
|
||||
* it's preferred to use the non dashed form of git commands, which means that
|
||||
you should prefer `"git foo"` to `"git-foo"`.
|
||||
you should prefer `git foo` to `git-foo`.
|
||||
|
||||
* splitting short options to separate words (prefer `"git foo -a -b"`
|
||||
to `"git foo -ab"`, the latter may not even work).
|
||||
* splitting short options to separate words (prefer `git foo -a -b`
|
||||
to `git foo -ab`, the latter may not even work).
|
||||
|
||||
* when a command line option takes an argument, use the 'sticked' form. In
|
||||
other words, write `"git foo -oArg"` instead of `"git foo -o Arg"` for short
|
||||
options, and `"git foo --long-opt=Arg"` instead of `"git foo --long-opt Arg"`
|
||||
other words, write `git foo -oArg` instead of `git foo -o Arg` for short
|
||||
options, and `git foo --long-opt=Arg` instead of `git foo --long-opt Arg`
|
||||
for long options. An option that takes optional option-argument must be
|
||||
written in the 'sticked' form.
|
||||
|
||||
* when you give a revision parameter to a command, make sure the parameter is
|
||||
not ambiguous with a name of a file in the work tree. E.g. do not write
|
||||
`"git log -1 HEAD"` but write `"git log -1 HEAD --"`; the former will not work
|
||||
`git log -1 HEAD` but write `git log -1 HEAD --`; the former will not work
|
||||
if you happen to have a file called `HEAD` in the work tree.
|
||||
|
||||
|
||||
@ -99,17 +99,17 @@ usage: git-describe [options] <committish>*
|
||||
|
||||
Negating options
|
||||
~~~~~~~~~~~~~~~~
|
||||
Options with long option names can be negated by prefixing `"--no-"`. For
|
||||
example, `"git branch"` has the option `"--track"` which is 'on' by default. You
|
||||
can use `"--no-track"` to override that behaviour. The same goes for `"--color"`
|
||||
and `"--no-color"`.
|
||||
Options with long option names can be negated by prefixing `--no-`. For
|
||||
example, `git branch` has the option `--track` which is 'on' by default. You
|
||||
can use `--no-track` to override that behaviour. The same goes for `--color`
|
||||
and `--no-color`.
|
||||
|
||||
|
||||
Aggregating short options
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Commands that support the enhanced option parser allow you to aggregate short
|
||||
options. This means that you can for example use `"git rm -rf"` or
|
||||
`"git clean -fdx"`.
|
||||
options. This means that you can for example use `git rm -rf` or
|
||||
`git clean -fdx`.
|
||||
|
||||
|
||||
Separating argument from the option
|
||||
|
@ -151,6 +151,10 @@ indicating whether the checkout was a branch checkout (changing branches,
|
||||
flag=1) or a file checkout (retrieving a file from the index, flag=0).
|
||||
This hook cannot affect the outcome of 'git-checkout'.
|
||||
|
||||
It is also run after 'git-clone', unless the --no-checkout (-n) option is
|
||||
used. The first parameter given to the hook is the null-ref, the second the
|
||||
ref of the new HEAD and the flag is always 1.
|
||||
|
||||
This hook can be used to perform repository validity checks, auto-display
|
||||
differences from the previous HEAD if different, or set working dir metadata
|
||||
properties.
|
||||
|
@ -31,8 +31,8 @@ precedence, the last matching pattern decides the outcome):
|
||||
|
||||
* Patterns read from a `.gitignore` file in the same directory
|
||||
as the path, or in any parent directory, with patterns in the
|
||||
higher level files (up to the root) being overridden by those in
|
||||
lower level files down to the directory containing the file.
|
||||
higher level files (up to the toplevel of the work tree) being overridden
|
||||
by those in lower level files down to the directory containing the file.
|
||||
These patterns match relative to the location of the
|
||||
`.gitignore` file. A project normally includes such
|
||||
`.gitignore` files in its repository, containing patterns for
|
||||
|
@ -262,7 +262,7 @@ This commit is referred to as a "merge commit", or sometimes just a
|
||||
'origin' is used for that purpose. New upstream updates
|
||||
will be fetched into remote <<def_tracking_branch,tracking branches>> named
|
||||
origin/name-of-upstream-branch, which you can see using
|
||||
"`git branch -r`".
|
||||
`git branch -r`.
|
||||
|
||||
[[def_pack]]pack::
|
||||
A set of objects which have been compressed into one file (to save space
|
||||
@ -449,6 +449,12 @@ This commit is referred to as a "merge commit", or sometimes just a
|
||||
An <<def_object,object>> which is not <<def_reachable,reachable>> from a
|
||||
<<def_branch,branch>>, <<def_tag,tag>>, or any other reference.
|
||||
|
||||
[[def_upstream_branch]]upstream branch::
|
||||
The default <<def_branch,branch>> that is merged into the branch in
|
||||
question (or the branch in question is rebased onto). It is configured
|
||||
via branch.<name>.remote and branch.<name>.merge. If the upstream branch
|
||||
of 'A' is 'origin/B' sometimes we say "'A' is tracking 'origin/B'".
|
||||
|
||||
[[def_working_tree]]working tree::
|
||||
The tree of actual checked out files. The working tree is
|
||||
normally equal to the <<def_HEAD,HEAD>> plus any local changes
|
||||
|
@ -5,22 +5,21 @@ canonical real names and email addresses.
|
||||
|
||||
In the simple form, each line in the file consists of the canonical
|
||||
real name of an author, whitespace, and an email address used in the
|
||||
commit (enclosed by '<' and '>') to map to the name. Thus, looks like
|
||||
this
|
||||
commit (enclosed by '<' and '>') to map to the name. For example:
|
||||
--
|
||||
Proper Name <commit@email.xx>
|
||||
--
|
||||
|
||||
The more complex forms are
|
||||
The more complex forms are:
|
||||
--
|
||||
<proper@email.xx> <commit@email.xx>
|
||||
--
|
||||
which allows mailmap to replace only the email part of a commit, and
|
||||
which allows mailmap to replace only the email part of a commit, and:
|
||||
--
|
||||
Proper Name <proper@email.xx> <commit@email.xx>
|
||||
--
|
||||
which allows mailmap to replace both the name and the email of a
|
||||
commit matching the specified commit email address, and
|
||||
commit matching the specified commit email address, and:
|
||||
--
|
||||
Proper Name <proper@email.xx> Commit Name <commit@email.xx>
|
||||
--
|
||||
@ -47,8 +46,8 @@ Jane Doe <jane@desktop.(none)>
|
||||
Joe R. Developer <joe@example.com>
|
||||
------------
|
||||
|
||||
Note how we don't need an entry for <jane@laptop.(none)>, because the
|
||||
real name of that author is correct already.
|
||||
Note how there is no need for an entry for <jane@laptop.(none)>, because the
|
||||
real name of that author is already correct.
|
||||
|
||||
Example 2: Your repository contains commits from the following
|
||||
authors:
|
||||
@ -62,7 +61,7 @@ claus <me@company.xx>
|
||||
CTO <cto@coompany.xx>
|
||||
------------
|
||||
|
||||
Then, you might want a `.mailmap` file looking like:
|
||||
Then you might want a `.mailmap` file that looks like:
|
||||
------------
|
||||
<cto@company.xx> <cto@coompany.xx>
|
||||
Some Dude <some@dude.xx> nick1 <bugs@company.xx>
|
||||
@ -72,4 +71,4 @@ Santa Claus <santa.claus@northpole.xx> <me@company.xx>
|
||||
------------
|
||||
|
||||
Use hash '#' for comments that are either on their own line, or after
|
||||
the email address.
|
||||
the email address.
|
||||
|
@ -1,21 +1,14 @@
|
||||
<!-- Based on callouts.xsl. Fixes man page callouts for DocBook 1.72 XSL -->
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<!-- manpage-1.72.xsl:
|
||||
special settings for manpages rendered from asciidoc+docbook
|
||||
handles peculiarities in docbook-xsl 1.72.0 -->
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
version="1.0">
|
||||
|
||||
<xsl:param name="man.output.quietly" select="1"/>
|
||||
<xsl:param name="refentry.meta.get.quietly" select="1"/>
|
||||
<xsl:import href="manpage-base.xsl"/>
|
||||
|
||||
<xsl:template match="co">
|
||||
<xsl:value-of select="concat('▓fB(',substring-after(@id,'-'),')▓fR')"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="calloutlist">
|
||||
<xsl:text>⌂sp </xsl:text>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:template>
|
||||
<xsl:template match="callout">
|
||||
<xsl:value-of select="concat('▓fB',substring-after(@arearefs,'-'),'. ▓fR')"/>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>⌂br </xsl:text>
|
||||
</xsl:template>
|
||||
<!-- these are the special values for the roff control characters
|
||||
needed for docbook-xsl 1.72.0 -->
|
||||
<xsl:param name="git.docbook.backslash">▓</xsl:param>
|
||||
<xsl:param name="git.docbook.dot" >⌂</xsl:param>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
35
Documentation/manpage-base.xsl
Normal file
35
Documentation/manpage-base.xsl
Normal file
@ -0,0 +1,35 @@
|
||||
<!-- manpage-base.xsl:
|
||||
special formatting for manpages rendered from asciidoc+docbook -->
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
version="1.0">
|
||||
|
||||
<!-- these params silence some output from xmlto -->
|
||||
<xsl:param name="man.output.quietly" select="1"/>
|
||||
<xsl:param name="refentry.meta.get.quietly" select="1"/>
|
||||
|
||||
<!-- convert asciidoc callouts to man page format;
|
||||
git.docbook.backslash and git.docbook.dot params
|
||||
must be supplied by another XSL file or other means -->
|
||||
<xsl:template match="co">
|
||||
<xsl:value-of select="concat(
|
||||
$git.docbook.backslash,'fB(',
|
||||
substring-after(@id,'-'),')',
|
||||
$git.docbook.backslash,'fR')"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="calloutlist">
|
||||
<xsl:value-of select="$git.docbook.dot"/>
|
||||
<xsl:text>sp </xsl:text>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:template>
|
||||
<xsl:template match="callout">
|
||||
<xsl:value-of select="concat(
|
||||
$git.docbook.backslash,'fB',
|
||||
substring-after(@arearefs,'-'),
|
||||
'. ',$git.docbook.backslash,'fR')"/>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:value-of select="$git.docbook.dot"/>
|
||||
<xsl:text>br </xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
17
Documentation/manpage-bold-literal.xsl
Normal file
17
Documentation/manpage-bold-literal.xsl
Normal file
@ -0,0 +1,17 @@
|
||||
<!-- manpage-bold-literal.xsl:
|
||||
special formatting for manpages rendered from asciidoc+docbook -->
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
version="1.0">
|
||||
|
||||
<!-- render literal text as bold (instead of plain or monospace);
|
||||
this makes literal text easier to distinguish in manpages
|
||||
viewed on a tty -->
|
||||
<xsl:template match="literal">
|
||||
<xsl:value-of select="$git.docbook.backslash"/>
|
||||
<xsl:text>fB</xsl:text>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:value-of select="$git.docbook.backslash"/>
|
||||
<xsl:text>fR</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
13
Documentation/manpage-normal.xsl
Normal file
13
Documentation/manpage-normal.xsl
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- manpage-normal.xsl:
|
||||
special settings for manpages rendered from asciidoc+docbook
|
||||
handles anything we want to keep away from docbook-xsl 1.72.0 -->
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
version="1.0">
|
||||
|
||||
<xsl:import href="manpage-base.xsl"/>
|
||||
|
||||
<!-- these are the normal values for the roff control characters -->
|
||||
<xsl:param name="git.docbook.backslash">\</xsl:param>
|
||||
<xsl:param name="git.docbook.dot" >.</xsl:param>
|
||||
|
||||
</xsl:stylesheet>
|
21
Documentation/manpage-suppress-sp.xsl
Normal file
21
Documentation/manpage-suppress-sp.xsl
Normal file
@ -0,0 +1,21 @@
|
||||
<!-- manpage-suppress-sp.xsl:
|
||||
special settings for manpages rendered from asciidoc+docbook
|
||||
handles erroneous, inline .sp in manpage output of some
|
||||
versions of docbook-xsl -->
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
version="1.0">
|
||||
|
||||
<!-- attempt to work around spurious .sp at the tail of the line
|
||||
that some versions of docbook stylesheets seem to add -->
|
||||
<xsl:template match="simpara">
|
||||
<xsl:variable name="content">
|
||||
<xsl:apply-templates/>
|
||||
</xsl:variable>
|
||||
<xsl:value-of select="normalize-space($content)"/>
|
||||
<xsl:if test="not(ancestor::authorblurb) and
|
||||
not(ancestor::personblurb)">
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
@ -3,15 +3,15 @@ MERGE STRATEGIES
|
||||
|
||||
resolve::
|
||||
This can only resolve two heads (i.e. the current branch
|
||||
and another branch you pulled from) using 3-way merge
|
||||
and another branch you pulled from) using a 3-way merge
|
||||
algorithm. It tries to carefully detect criss-cross
|
||||
merge ambiguities and is considered generally safe and
|
||||
fast.
|
||||
|
||||
recursive::
|
||||
This can only resolve two heads using 3-way merge
|
||||
algorithm. When there are more than one common
|
||||
ancestors that can be used for 3-way merge, it creates a
|
||||
This can only resolve two heads using a 3-way merge
|
||||
algorithm. When there is more than one common
|
||||
ancestor that can be used for 3-way merge, it creates a
|
||||
merged tree of the common ancestors and uses that as
|
||||
the reference tree for the 3-way merge. This has been
|
||||
reported to result in fewer merge conflicts without
|
||||
@ -22,11 +22,11 @@ recursive::
|
||||
pulling or merging one branch.
|
||||
|
||||
octopus::
|
||||
This resolves more than two-head case, but refuses to do
|
||||
complex merge that needs manual resolution. It is
|
||||
This resolves cases with more than two heads, but refuses to do
|
||||
a complex merge that needs manual resolution. It is
|
||||
primarily meant to be used for bundling topic branch
|
||||
heads together. This is the default merge strategy when
|
||||
pulling or merging more than one branches.
|
||||
pulling or merging more than one branch.
|
||||
|
||||
ours::
|
||||
This resolves any number of heads, but the result of the
|
||||
|
@ -121,6 +121,7 @@ The placeholders are:
|
||||
- '%d': ref names, like the --decorate option of linkgit:git-log[1]
|
||||
- '%e': encoding
|
||||
- '%s': subject
|
||||
- '%f': sanitized subject line, suitable for a filename
|
||||
- '%b': body
|
||||
- '%Cred': switch color to red
|
||||
- '%Cgreen': switch color to green
|
||||
@ -152,3 +153,12 @@ $ git log -2 --pretty=tformat:%h 4da45bef \
|
||||
4da45be
|
||||
7134973
|
||||
---------------------
|
||||
+
|
||||
In addition, any unrecognized string that has a `%` in it is interpreted
|
||||
as if it has `tformat:` in front of it. For example, these two are
|
||||
equivalent:
|
||||
+
|
||||
---------------------
|
||||
$ git log -2 --pretty=tformat:%h 4da45bef
|
||||
$ git log -2 --pretty=%h 4da45bef
|
||||
---------------------
|
||||
|
@ -1,4 +1,5 @@
|
||||
--pretty[='<format>']::
|
||||
--format[='<format>']::
|
||||
|
||||
Pretty-print the contents of the commit logs in a given format,
|
||||
where '<format>' can be one of 'oneline', 'short', 'medium',
|
||||
@ -17,6 +18,10 @@ configuration (see linkgit:git-config[1]).
|
||||
This should make "--pretty=oneline" a whole lot more readable for
|
||||
people using 80-column terminals.
|
||||
|
||||
--oneline::
|
||||
This is a shorthand for "--pretty=oneline --abbrev-commit"
|
||||
used together.
|
||||
|
||||
--encoding[=<encoding>]::
|
||||
The commit objects record the encoding used for the log message
|
||||
in their encoding header; this option can be used to tell the
|
||||
|
@ -140,38 +140,38 @@ limiting may be applied.
|
||||
--
|
||||
|
||||
-n 'number'::
|
||||
--max-count='number'::
|
||||
--max-count=<number>::
|
||||
|
||||
Limit the number of commits output.
|
||||
|
||||
--skip='number'::
|
||||
--skip=<number>::
|
||||
|
||||
Skip 'number' commits before starting to show the commit output.
|
||||
|
||||
--since='date'::
|
||||
--after='date'::
|
||||
--since=<date>::
|
||||
--after=<date>::
|
||||
|
||||
Show commits more recent than a specific date.
|
||||
|
||||
--until='date'::
|
||||
--before='date'::
|
||||
--until=<date>::
|
||||
--before=<date>::
|
||||
|
||||
Show commits older than a specific date.
|
||||
|
||||
ifdef::git-rev-list[]
|
||||
--max-age='timestamp'::
|
||||
--min-age='timestamp'::
|
||||
--max-age=<timestamp>::
|
||||
--min-age=<timestamp>::
|
||||
|
||||
Limit the commits output to specified time range.
|
||||
endif::git-rev-list[]
|
||||
|
||||
--author='pattern'::
|
||||
--committer='pattern'::
|
||||
--author=<pattern>::
|
||||
--committer=<pattern>::
|
||||
|
||||
Limit the commits output to ones with author/committer
|
||||
header lines that match the specified pattern (regular expression).
|
||||
|
||||
--grep='pattern'::
|
||||
--grep=<pattern>::
|
||||
|
||||
Limit the commits output to ones with log message that
|
||||
matches the specified pattern (regular expression).
|
||||
|
@ -148,22 +148,22 @@ outputting that information, if desired.
|
||||
------------
|
||||
*
|
||||
*
|
||||
M
|
||||
*
|
||||
|\
|
||||
* |
|
||||
| | *
|
||||
| \ \
|
||||
| \ \
|
||||
M-. \ \
|
||||
*-. \ \
|
||||
|\ \ \ \
|
||||
| | * | |
|
||||
| | | | | *
|
||||
| | | | | *
|
||||
| | | | | M
|
||||
| | | | | *
|
||||
| | | | | |\
|
||||
| | | | | | *
|
||||
| * | | | | |
|
||||
| | | | | M \
|
||||
| | | | | * \
|
||||
| | | | | |\ |
|
||||
| | | | * | | |
|
||||
| | | | * | | |
|
||||
|
@ -66,6 +66,12 @@ Steps to parse options
|
||||
non-option arguments in `argv[]`.
|
||||
`argc` is updated appropriately because of the assignment.
|
||||
+
|
||||
You can also pass NULL instead of a usage array as fourth parameter of
|
||||
parse_options(), to avoid displaying a help screen with usage info and
|
||||
option list. This should only be done if necessary, e.g. to implement
|
||||
a limited parser for only a subset of the options that needs to be run
|
||||
before the full parser, which in turn shows the full help message.
|
||||
+
|
||||
Flags are the bitwise-or of:
|
||||
|
||||
`PARSE_OPT_KEEP_DASHDASH`::
|
||||
@ -77,6 +83,28 @@ Flags are the bitwise-or of:
|
||||
Using this flag, processing is stopped at the first non-option
|
||||
argument.
|
||||
|
||||
`PARSE_OPT_KEEP_ARGV0`::
|
||||
Keep the first argument, which contains the program name. It's
|
||||
removed from argv[] by default.
|
||||
|
||||
`PARSE_OPT_KEEP_UNKNOWN`::
|
||||
Keep unknown arguments instead of erroring out. This doesn't
|
||||
work for all combinations of arguments as users might expect
|
||||
it to do. E.g. if the first argument in `--unknown --known`
|
||||
takes a value (which we can't know), the second one is
|
||||
mistakenly interpreted as a known option. Similarly, if
|
||||
`PARSE_OPT_STOP_AT_NON_OPTION` is set, the second argument in
|
||||
`--unknown value` will be mistakenly interpreted as a
|
||||
non-option, not as a value belonging to the unknown option,
|
||||
the parser early. That's why parse_options() errors out if
|
||||
both options are set.
|
||||
|
||||
`PARSE_OPT_NO_INTERNAL_HELP`::
|
||||
By default, parse_options() handles `-h`, `--help` and
|
||||
`--help-all` internally, by showing a help screen. This option
|
||||
turns it off and allows one to add custom handlers for these
|
||||
options, or to just leave them unknown.
|
||||
|
||||
Data Structure
|
||||
--------------
|
||||
|
||||
|
@ -188,7 +188,7 @@ As you can see, a commit shows who made the latest change, what they
|
||||
did, and why.
|
||||
|
||||
Every commit has a 40-hexdigit id, sometimes called the "object name" or the
|
||||
"SHA1 id", shown on the first line of the "git-show" output. You can usually
|
||||
"SHA-1 id", shown on the first line of the "git show" output. You can usually
|
||||
refer to a commit by a shorter name, such as a tag or a branch name, but this
|
||||
longer name can also be useful. Most importantly, it is a globally unique
|
||||
name for this commit: so if you tell somebody else the object name (for
|
||||
@ -307,7 +307,7 @@ ref: refs/heads/master
|
||||
Examining an old version without creating a new branch
|
||||
------------------------------------------------------
|
||||
|
||||
The git-checkout command normally expects a branch head, but will also
|
||||
The `git checkout` command normally expects a branch head, but will also
|
||||
accept an arbitrary commit; for example, you can check out the commit
|
||||
referenced by a tag:
|
||||
|
||||
@ -320,7 +320,7 @@ If you want to create a new branch from this checkout, you may do so
|
||||
HEAD is now at 427abfa... Linux v2.6.17
|
||||
------------------------------------------------
|
||||
|
||||
The HEAD then refers to the SHA1 of the commit instead of to a branch,
|
||||
The HEAD then refers to the SHA-1 of the commit instead of to a branch,
|
||||
and git branch shows that you are no longer on a branch:
|
||||
|
||||
------------------------------------------------
|
||||
@ -400,7 +400,7 @@ references with the same shorthand name, see the "SPECIFYING
|
||||
REVISIONS" section of linkgit:git-rev-parse[1].
|
||||
|
||||
[[Updating-a-repository-With-git-fetch]]
|
||||
Updating a repository with git-fetch
|
||||
Updating a repository with git fetch
|
||||
------------------------------------
|
||||
|
||||
Eventually the developer cloned from will do additional work in her
|
||||
@ -427,7 +427,7 @@ $ git fetch linux-nfs
|
||||
-------------------------------------------------
|
||||
|
||||
New remote-tracking branches will be stored under the shorthand name
|
||||
that you gave "git-remote add", in this case linux-nfs:
|
||||
that you gave "git remote add", in this case linux-nfs:
|
||||
|
||||
-------------------------------------------------
|
||||
$ git branch -r
|
||||
@ -516,7 +516,7 @@ $ git bisect reset
|
||||
|
||||
to return you to the branch you were on before.
|
||||
|
||||
Note that the version which git-bisect checks out for you at each
|
||||
Note that the version which `git bisect` checks out for you at each
|
||||
point is just a suggestion, and you're free to try a different
|
||||
version if you think it would be a good idea. For example,
|
||||
occasionally you may land on a commit that broke something unrelated;
|
||||
@ -592,11 +592,11 @@ In addition to HEAD, there are several other special names for
|
||||
commits:
|
||||
|
||||
Merges (to be discussed later), as well as operations such as
|
||||
git-reset, which change the currently checked-out commit, generally
|
||||
`git reset`, which change the currently checked-out commit, generally
|
||||
set ORIG_HEAD to the value HEAD had before the current operation.
|
||||
|
||||
The git-fetch operation always stores the head of the last fetched
|
||||
branch in FETCH_HEAD. For example, if you run git fetch without
|
||||
The `git fetch` operation always stores the head of the last fetched
|
||||
branch in FETCH_HEAD. For example, if you run `git fetch` without
|
||||
specifying a local branch as the target of the operation
|
||||
|
||||
-------------------------------------------------
|
||||
@ -739,7 +739,7 @@ $ git log --pretty=oneline origin..mybranch | wc -l
|
||||
-------------------------------------------------
|
||||
|
||||
Alternatively, you may often see this sort of thing done with the
|
||||
lower-level command linkgit:git-rev-list[1], which just lists the SHA1's
|
||||
lower-level command linkgit:git-rev-list[1], which just lists the SHA-1's
|
||||
of all the given commits:
|
||||
|
||||
-------------------------------------------------
|
||||
@ -1073,9 +1073,9 @@ $ git diff
|
||||
|
||||
shows the difference between the working tree and the index file.
|
||||
|
||||
Note that "git-add" always adds just the current contents of a file
|
||||
Note that "git add" always adds just the current contents of a file
|
||||
to the index; further changes to the same file will be ignored unless
|
||||
you run git-add on the file again.
|
||||
you run `git add` on the file again.
|
||||
|
||||
When you're ready, just run
|
||||
|
||||
@ -1136,10 +1136,10 @@ Ignoring files
|
||||
A project will often generate files that you do 'not' want to track with git.
|
||||
This typically includes files generated by a build process or temporary
|
||||
backup files made by your editor. Of course, 'not' tracking files with git
|
||||
is just a matter of 'not' calling "`git-add`" on them. But it quickly becomes
|
||||
is just a matter of 'not' calling `git add` on them. But it quickly becomes
|
||||
annoying to have these untracked files lying around; e.g. they make
|
||||
"`git add .`" practically useless, and they keep showing up in the output of
|
||||
"`git status`".
|
||||
`git add .` practically useless, and they keep showing up in the output of
|
||||
`git status`.
|
||||
|
||||
You can tell git to ignore certain files by creating a file called .gitignore
|
||||
in the top level of your working directory, with contents such as:
|
||||
@ -1349,7 +1349,7 @@ $ git add file.txt
|
||||
-------------------------------------------------
|
||||
|
||||
the different stages of that file will be "collapsed", after which
|
||||
git-diff will (by default) no longer show diffs for that file.
|
||||
`git diff` will (by default) no longer show diffs for that file.
|
||||
|
||||
[[undoing-a-merge]]
|
||||
Undoing a merge
|
||||
@ -1446,7 +1446,7 @@ Fixing a mistake by rewriting history
|
||||
|
||||
If the problematic commit is the most recent commit, and you have not
|
||||
yet made that commit public, then you may just
|
||||
<<undoing-a-merge,destroy it using git-reset>>.
|
||||
<<undoing-a-merge,destroy it using `git reset`>>.
|
||||
|
||||
Alternatively, you
|
||||
can edit the working directory and update the index to fix your
|
||||
@ -1474,7 +1474,7 @@ Checking out an old version of a file
|
||||
|
||||
In the process of undoing a previous bad change, you may find it
|
||||
useful to check out an older version of a particular file using
|
||||
linkgit:git-checkout[1]. We've used git-checkout before to switch
|
||||
linkgit:git-checkout[1]. We've used `git checkout` before to switch
|
||||
branches, but it has quite different behavior if it is given a path
|
||||
name: the command
|
||||
|
||||
@ -1542,7 +1542,7 @@ $ git gc
|
||||
-------------------------------------------------
|
||||
|
||||
to recompress the archive. This can be very time-consuming, so
|
||||
you may prefer to run git-gc when you are not doing other work.
|
||||
you may prefer to run `git gc` when you are not doing other work.
|
||||
|
||||
|
||||
[[ensuring-reliability]]
|
||||
@ -1634,7 +1634,7 @@ In some situations the reflog may not be able to save you. For example,
|
||||
suppose you delete a branch, then realize you need the history it
|
||||
contained. The reflog is also deleted; however, if you have not yet
|
||||
pruned the repository, then you may still be able to find the lost
|
||||
commits in the dangling objects that git-fsck reports. See
|
||||
commits in the dangling objects that `git fsck` reports. See
|
||||
<<dangling-objects>> for the details.
|
||||
|
||||
-------------------------------------------------
|
||||
@ -1676,7 +1676,7 @@ Sharing development with others
|
||||
===============================
|
||||
|
||||
[[getting-updates-With-git-pull]]
|
||||
Getting updates with git-pull
|
||||
Getting updates with git pull
|
||||
-----------------------------
|
||||
|
||||
After you clone a repository and make a few changes of your own, you
|
||||
@ -1722,7 +1722,7 @@ repository that you pulled from.
|
||||
<<fast-forwards,fast forward>>; instead, your branch will just be
|
||||
updated to point to the latest commit from the upstream branch.)
|
||||
|
||||
The git-pull command can also be given "." as the "remote" repository,
|
||||
The `git pull` command can also be given "." as the "remote" repository,
|
||||
in which case it just merges in a branch from the current repository; so
|
||||
the commands
|
||||
|
||||
@ -1795,7 +1795,7 @@ Public git repositories
|
||||
Another way to submit changes to a project is to tell the maintainer
|
||||
of that project to pull the changes from your repository using
|
||||
linkgit:git-pull[1]. In the section "<<getting-updates-With-git-pull,
|
||||
Getting updates with git-pull>>" we described this as a way to get
|
||||
Getting updates with `git pull`>>" we described this as a way to get
|
||||
updates from the "main" repository, but it works just as well in the
|
||||
other direction.
|
||||
|
||||
@ -1847,7 +1847,7 @@ Setting up a public repository
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Assume your personal repository is in the directory ~/proj. We
|
||||
first create a new clone of the repository and tell git-daemon that it
|
||||
first create a new clone of the repository and tell `git daemon` that it
|
||||
is meant to be public:
|
||||
|
||||
-------------------------------------------------
|
||||
@ -1878,10 +1878,10 @@ repository>>", below.
|
||||
Otherwise, all you need to do is start linkgit:git-daemon[1]; it will
|
||||
listen on port 9418. By default, it will allow access to any directory
|
||||
that looks like a git directory and contains the magic file
|
||||
git-daemon-export-ok. Passing some directory paths as git-daemon
|
||||
git-daemon-export-ok. Passing some directory paths as `git daemon`
|
||||
arguments will further restrict the exports to those paths.
|
||||
|
||||
You can also run git-daemon as an inetd service; see the
|
||||
You can also run `git daemon` as an inetd service; see the
|
||||
linkgit:git-daemon[1] man page for details. (See especially the
|
||||
examples section.)
|
||||
|
||||
@ -1942,7 +1942,7 @@ or just
|
||||
$ git push ssh://yourserver.com/~you/proj.git master
|
||||
-------------------------------------------------
|
||||
|
||||
As with git-fetch, git-push will complain if this does not result in a
|
||||
As with `git fetch`, `git push` will complain if this does not result in a
|
||||
<<fast-forwards,fast forward>>; see the following section for details on
|
||||
handling this case.
|
||||
|
||||
@ -1952,7 +1952,7 @@ repository that has a checked-out working tree, but the working tree
|
||||
will not be updated by the push. This may lead to unexpected results if
|
||||
the branch you push to is the currently checked-out branch!
|
||||
|
||||
As with git-fetch, you may also set up configuration options to
|
||||
As with `git fetch`, you may also set up configuration options to
|
||||
save typing; so, for example, after
|
||||
|
||||
-------------------------------------------------
|
||||
@ -1988,13 +1988,13 @@ error: failed to push to 'ssh://yourserver.com/~you/proj.git'
|
||||
|
||||
This can happen, for example, if you:
|
||||
|
||||
- use `git-reset --hard` to remove already-published commits, or
|
||||
- use `git-commit --amend` to replace already-published commits
|
||||
- use `git reset --hard` to remove already-published commits, or
|
||||
- use `git commit --amend` to replace already-published commits
|
||||
(as in <<fixing-a-mistake-by-rewriting-history>>), or
|
||||
- use `git-rebase` to rebase any already-published commits (as
|
||||
- use `git rebase` to rebase any already-published commits (as
|
||||
in <<using-git-rebase>>).
|
||||
|
||||
You may force git-push to perform the update anyway by preceding the
|
||||
You may force `git push` to perform the update anyway by preceding the
|
||||
branch name with a plus sign:
|
||||
|
||||
-------------------------------------------------
|
||||
@ -2036,7 +2036,7 @@ advantages over the central shared repository:
|
||||
|
||||
- Git's ability to quickly import and merge patches allows a
|
||||
single maintainer to process incoming changes even at very
|
||||
high rates. And when that becomes too much, git-pull provides
|
||||
high rates. And when that becomes too much, `git pull` provides
|
||||
an easy way for that maintainer to delegate this job to other
|
||||
maintainers while still allowing optional review of incoming
|
||||
changes.
|
||||
@ -2404,7 +2404,7 @@ use them, and then explain some of the problems that can arise because
|
||||
you are rewriting history.
|
||||
|
||||
[[using-git-rebase]]
|
||||
Keeping a patch series up to date using git-rebase
|
||||
Keeping a patch series up to date using git rebase
|
||||
--------------------------------------------------
|
||||
|
||||
Suppose that you create a branch "mywork" on a remote-tracking branch
|
||||
@ -2468,9 +2468,9 @@ patches to the new mywork. The result will look like:
|
||||
................................................
|
||||
|
||||
In the process, it may discover conflicts. In that case it will stop
|
||||
and allow you to fix the conflicts; after fixing conflicts, use "git-add"
|
||||
and allow you to fix the conflicts; after fixing conflicts, use `git add`
|
||||
to update the index with those contents, and then, instead of
|
||||
running git-commit, just run
|
||||
running `git commit`, just run
|
||||
|
||||
-------------------------------------------------
|
||||
$ git rebase --continue
|
||||
@ -2508,7 +2508,7 @@ with
|
||||
$ git tag bad mywork~5
|
||||
-------------------------------------------------
|
||||
|
||||
(Either gitk or git-log may be useful for finding the commit.)
|
||||
(Either gitk or `git log` may be useful for finding the commit.)
|
||||
|
||||
Then check out that commit, edit it, and rebase the rest of the series
|
||||
on top of it (note that we could check out the commit on a temporary
|
||||
@ -2549,12 +2549,12 @@ $ gitk origin..mywork &
|
||||
|
||||
and browse through the list of patches in the mywork branch using gitk,
|
||||
applying them (possibly in a different order) to mywork-new using
|
||||
cherry-pick, and possibly modifying them as you go using `commit --amend`.
|
||||
cherry-pick, and possibly modifying them as you go using `git commit --amend`.
|
||||
The linkgit:git-gui[1] command may also help as it allows you to
|
||||
individually select diff hunks for inclusion in the index (by
|
||||
right-clicking on the diff hunk and choosing "Stage Hunk for Commit").
|
||||
|
||||
Another technique is to use git-format-patch to create a series of
|
||||
Another technique is to use `git format-patch` to create a series of
|
||||
patches, then reset the state to before the patches:
|
||||
|
||||
-------------------------------------------------
|
||||
@ -2662,7 +2662,7 @@ you know is that D is bad, that Z is good, and that
|
||||
linkgit:git-bisect[1] identifies C as the culprit, how will you
|
||||
figure out that the problem is due to this change in semantics?
|
||||
|
||||
When the result of a git-bisect is a non-merge commit, you should
|
||||
When the result of a `git bisect` is a non-merge commit, you should
|
||||
normally be able to discover the problem by examining just that commit.
|
||||
Developers can make this easy by breaking their changes into small
|
||||
self-contained commits. That won't help in the case above, however,
|
||||
@ -2725,7 +2725,7 @@ master branch. In more detail:
|
||||
git fetch and fast-forwards
|
||||
---------------------------
|
||||
|
||||
In the previous example, when updating an existing branch, "git-fetch"
|
||||
In the previous example, when updating an existing branch, "git fetch"
|
||||
checks to make sure that the most recent commit on the remote
|
||||
branch is a descendant of the most recent commit on your copy of the
|
||||
branch before updating your copy of the branch to point at the new
|
||||
@ -2751,7 +2751,7 @@ resulting in a situation like:
|
||||
o--o--o <-- new head of the branch
|
||||
................................................
|
||||
|
||||
In this case, "git-fetch" will fail, and print out a warning.
|
||||
In this case, "git fetch" will fail, and print out a warning.
|
||||
|
||||
In that case, you can still force git to update to the new head, as
|
||||
described in the following section. However, note that in the
|
||||
@ -2760,7 +2760,7 @@ unless you've already created a reference of your own pointing to
|
||||
them.
|
||||
|
||||
[[forcing-fetch]]
|
||||
Forcing git-fetch to do non-fast-forward updates
|
||||
Forcing git fetch to do non-fast-forward updates
|
||||
------------------------------------------------
|
||||
|
||||
If git fetch fails because the new head of a branch is not a
|
||||
@ -2865,8 +2865,8 @@ The Object Database
|
||||
We already saw in <<understanding-commits>> that all commits are stored
|
||||
under a 40-digit "object name". In fact, all the information needed to
|
||||
represent the history of a project is stored in objects with such names.
|
||||
In each case the name is calculated by taking the SHA1 hash of the
|
||||
contents of the object. The SHA1 hash is a cryptographic hash function.
|
||||
In each case the name is calculated by taking the SHA-1 hash of the
|
||||
contents of the object. The SHA-1 hash is a cryptographic hash function.
|
||||
What that means to us is that it is impossible to find two different
|
||||
objects with the same name. This has a number of advantages; among
|
||||
others:
|
||||
@ -2877,10 +2877,10 @@ others:
|
||||
same content stored in two repositories will always be stored under
|
||||
the same name.
|
||||
- Git can detect errors when it reads an object, by checking that the
|
||||
object's name is still the SHA1 hash of its contents.
|
||||
object's name is still the SHA-1 hash of its contents.
|
||||
|
||||
(See <<object-details>> for the details of the object formatting and
|
||||
SHA1 calculation.)
|
||||
SHA-1 calculation.)
|
||||
|
||||
There are four different types of objects: "blob", "tree", "commit", and
|
||||
"tag".
|
||||
@ -2926,9 +2926,9 @@ committer Junio C Hamano <gitster@pobox.com> 1187591163 -0700
|
||||
|
||||
As you can see, a commit is defined by:
|
||||
|
||||
- a tree: The SHA1 name of a tree object (as defined below), representing
|
||||
- a tree: The SHA-1 name of a tree object (as defined below), representing
|
||||
the contents of a directory at a certain point in time.
|
||||
- parent(s): The SHA1 name of some number of commits which represent the
|
||||
- parent(s): The SHA-1 name of some number of commits which represent the
|
||||
immediately previous step(s) in the history of the project. The
|
||||
example above has one parent; merge commits may have more than
|
||||
one. A commit with no parents is called a "root" commit, and
|
||||
@ -2977,13 +2977,13 @@ $ git ls-tree fb3a8bdd0ce
|
||||
------------------------------------------------
|
||||
|
||||
As you can see, a tree object contains a list of entries, each with a
|
||||
mode, object type, SHA1 name, and name, sorted by name. It represents
|
||||
mode, object type, SHA-1 name, and name, sorted by name. It represents
|
||||
the contents of a single directory tree.
|
||||
|
||||
The object type may be a blob, representing the contents of a file, or
|
||||
another tree, representing the contents of a subdirectory. Since trees
|
||||
and blobs, like all other objects, are named by the SHA1 hash of their
|
||||
contents, two trees have the same SHA1 name if and only if their
|
||||
and blobs, like all other objects, are named by the SHA-1 hash of their
|
||||
contents, two trees have the same SHA-1 name if and only if their
|
||||
contents (including, recursively, the contents of all subdirectories)
|
||||
are identical. This allows git to quickly determine the differences
|
||||
between two related tree objects, since it can ignore any entries with
|
||||
@ -3029,15 +3029,15 @@ currently checked out.
|
||||
Trust
|
||||
~~~~~
|
||||
|
||||
If you receive the SHA1 name of a blob from one source, and its contents
|
||||
If you receive the SHA-1 name of a blob from one source, and its contents
|
||||
from another (possibly untrusted) source, you can still trust that those
|
||||
contents are correct as long as the SHA1 name agrees. This is because
|
||||
the SHA1 is designed so that it is infeasible to find different contents
|
||||
contents are correct as long as the SHA-1 name agrees. This is because
|
||||
the SHA-1 is designed so that it is infeasible to find different contents
|
||||
that produce the same hash.
|
||||
|
||||
Similarly, you need only trust the SHA1 name of a top-level tree object
|
||||
Similarly, you need only trust the SHA-1 name of a top-level tree object
|
||||
to trust the contents of the entire directory that it refers to, and if
|
||||
you receive the SHA1 name of a commit from a trusted source, then you
|
||||
you receive the SHA-1 name of a commit from a trusted source, then you
|
||||
can easily verify the entire history of commits reachable through
|
||||
parents of that commit, and all of those contents of the trees referred
|
||||
to by those commits.
|
||||
@ -3049,7 +3049,7 @@ that you trust that commit, and the immutability of the history of
|
||||
commits tells others that they can trust the whole history.
|
||||
|
||||
In other words, you can easily validate a whole archive by just
|
||||
sending out a single email that tells the people the name (SHA1 hash)
|
||||
sending out a single email that tells the people the name (SHA-1 hash)
|
||||
of the top commit, and digitally sign that email using something
|
||||
like GPG/PGP.
|
||||
|
||||
@ -3090,7 +3090,7 @@ How git stores objects efficiently: pack files
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Newly created objects are initially created in a file named after the
|
||||
object's SHA1 hash (stored in .git/objects).
|
||||
object's SHA-1 hash (stored in .git/objects).
|
||||
|
||||
Unfortunately this system becomes inefficient once a project has a
|
||||
lot of objects. Try this on an old project:
|
||||
@ -3131,7 +3131,7 @@ $ git prune
|
||||
|
||||
to remove any of the "loose" objects that are now contained in the
|
||||
pack. This will also remove any unreferenced objects (which may be
|
||||
created when, for example, you use "git-reset" to remove a commit).
|
||||
created when, for example, you use "git reset" to remove a commit).
|
||||
You can verify that the loose objects are gone by looking at the
|
||||
.git/objects directory or by running
|
||||
|
||||
@ -3160,7 +3160,7 @@ branch still exists, as does everything it pointed to. The branch
|
||||
pointer itself just doesn't, since you replaced it with another one.
|
||||
|
||||
There are also other situations that cause dangling objects. For
|
||||
example, a "dangling blob" may arise because you did a "git-add" of a
|
||||
example, a "dangling blob" may arise because you did a "git add" of a
|
||||
file, but then, before you actually committed it and made it part of the
|
||||
bigger picture, you changed something else in that file and committed
|
||||
that *updated* thing--the old state that you added originally ends up
|
||||
@ -3210,7 +3210,7 @@ Usually, dangling blobs and trees aren't very interesting. They're
|
||||
almost always the result of either being a half-way mergebase (the blob
|
||||
will often even have the conflict markers from a merge in it, if you
|
||||
have had conflicting merges that you fixed up by hand), or simply
|
||||
because you interrupted a "git-fetch" with ^C or something like that,
|
||||
because you interrupted a "git fetch" with ^C or something like that,
|
||||
leaving _some_ of the new objects in the object database, but just
|
||||
dangling and useless.
|
||||
|
||||
@ -3225,9 +3225,9 @@ and they'll be gone. But you should only run "git prune" on a quiescent
|
||||
repository--it's kind of like doing a filesystem fsck recovery: you
|
||||
don't want to do that while the filesystem is mounted.
|
||||
|
||||
(The same is true of "git-fsck" itself, btw, but since
|
||||
git-fsck never actually *changes* the repository, it just reports
|
||||
on what it found, git-fsck itself is never "dangerous" to run.
|
||||
(The same is true of "git fsck" itself, btw, but since
|
||||
`git fsck` never actually *changes* the repository, it just reports
|
||||
on what it found, `git fsck` itself is never 'dangerous' to run.
|
||||
Running it while somebody is actually changing the repository can cause
|
||||
confusing and scary messages, but it won't actually do anything bad. In
|
||||
contrast, running "git prune" while somebody is actively changing the
|
||||
@ -3297,7 +3297,7 @@ $ git hash-object -w somedirectory/myfile
|
||||
------------------------------------------------
|
||||
|
||||
which will create and store a blob object with the contents of
|
||||
somedirectory/myfile, and output the sha1 of that object. if you're
|
||||
somedirectory/myfile, and output the SHA-1 of that object. if you're
|
||||
extremely lucky it might be 4b9458b3786228369c63936db65827de3cc06200, in
|
||||
which case you've guessed right, and the corruption is fixed!
|
||||
|
||||
@ -3359,7 +3359,7 @@ The index
|
||||
-----------
|
||||
|
||||
The index is a binary file (generally kept in .git/index) containing a
|
||||
sorted list of path names, each with permissions and the SHA1 of a blob
|
||||
sorted list of path names, each with permissions and the SHA-1 of a blob
|
||||
object; linkgit:git-ls-files[1] can show you the contents of the index:
|
||||
|
||||
-------------------------------------------------
|
||||
@ -3489,14 +3489,14 @@ done
|
||||
|
||||
NOTE: Do not use local URLs here if you plan to publish your superproject!
|
||||
|
||||
See what files `git-submodule` created:
|
||||
See what files `git submodule` created:
|
||||
|
||||
-------------------------------------------------
|
||||
$ ls -a
|
||||
. .. .git .gitmodules a b c d
|
||||
-------------------------------------------------
|
||||
|
||||
The `git-submodule add <repo> <path>` command does a couple of things:
|
||||
The `git submodule add <repo> <path>` command does a couple of things:
|
||||
|
||||
- It clones the submodule from <repo> to the given <path> under the
|
||||
current directory and by default checks out the master branch.
|
||||
@ -3542,7 +3542,7 @@ init` to add the submodule repository URLs to `.git/config`:
|
||||
$ git submodule init
|
||||
-------------------------------------------------
|
||||
|
||||
Now use `git-submodule update` to clone the repositories and check out the
|
||||
Now use `git submodule update` to clone the repositories and check out the
|
||||
commits specified in the superproject:
|
||||
|
||||
-------------------------------------------------
|
||||
@ -3552,8 +3552,8 @@ $ ls -a
|
||||
. .. .git a.txt
|
||||
-------------------------------------------------
|
||||
|
||||
One major difference between `git-submodule update` and `git-submodule add` is
|
||||
that `git-submodule update` checks out a specific commit, rather than the tip
|
||||
One major difference between `git submodule update` and `git submodule add` is
|
||||
that `git submodule update` checks out a specific commit, rather than the tip
|
||||
of a branch. It's like checking out a tag: the head is detached, so you're not
|
||||
working on a branch.
|
||||
|
||||
@ -3754,7 +3754,7 @@ unsaved state that you might want to restore later!) your current
|
||||
index. Normal operation is just
|
||||
|
||||
-------------------------------------------------
|
||||
$ git read-tree <sha1 of tree>
|
||||
$ git read-tree <SHA-1 of tree>
|
||||
-------------------------------------------------
|
||||
|
||||
and your index file will now be equivalent to the tree that you saved
|
||||
@ -3769,7 +3769,7 @@ You update your working directory from the index by "checking out"
|
||||
files. This is not a very common operation, since normally you'd just
|
||||
keep your files updated, and rather than write to your working
|
||||
directory, you'd tell the index files about the changes in your
|
||||
working directory (i.e. `git-update-index`).
|
||||
working directory (i.e. `git update-index`).
|
||||
|
||||
However, if you decide to jump to a new version, or check out somebody
|
||||
else's version, or just restore a previous tree, you'd populate your
|
||||
@ -3782,7 +3782,7 @@ $ git checkout-index filename
|
||||
|
||||
or, if you want to check out all of the index, use `-a`.
|
||||
|
||||
NOTE! git-checkout-index normally refuses to overwrite old files, so
|
||||
NOTE! `git checkout-index` normally refuses to overwrite old files, so
|
||||
if you have an old version of the tree already checked out, you will
|
||||
need to use the "-f" flag ('before' the "-a" flag or the filename) to
|
||||
'force' the checkout.
|
||||
@ -3820,7 +3820,7 @@ $ git commit-tree <tree> -p <parent> [-p <parent2> ..]
|
||||
and then giving the reason for the commit on stdin (either through
|
||||
redirection from a pipe or file, or by just typing it at the tty).
|
||||
|
||||
git-commit-tree will return the name of the object that represents
|
||||
`git commit-tree` will return the name of the object that represents
|
||||
that commit, and you should save it away for later use. Normally,
|
||||
you'd commit a new `HEAD` state, and while git doesn't care where you
|
||||
save the note about that state, in practice we tend to just write the
|
||||
@ -3889,7 +3889,7 @@ $ git cat-file blob|tree|commit|tag <objectname>
|
||||
|
||||
to show its contents. NOTE! Trees have binary content, and as a result
|
||||
there is a special helper for showing that content, called
|
||||
`git-ls-tree`, which turns the binary content into a more easily
|
||||
`git ls-tree`, which turns the binary content into a more easily
|
||||
readable form.
|
||||
|
||||
It's especially instructive to look at "commit" objects, since those
|
||||
@ -3978,13 +3978,13 @@ $ git ls-files --unmerged
|
||||
------------------------------------------------
|
||||
|
||||
Each line of the `git ls-files --unmerged` output begins with
|
||||
the blob mode bits, blob SHA1, 'stage number', and the
|
||||
the blob mode bits, blob SHA-1, 'stage number', and the
|
||||
filename. The 'stage number' is git's way to say which tree it
|
||||
came from: stage 1 corresponds to `$orig` tree, stage 2 `HEAD`
|
||||
tree, and stage3 `$target` tree.
|
||||
|
||||
Earlier we said that trivial merges are done inside
|
||||
`git-read-tree -m`. For example, if the file did not change
|
||||
`git read-tree -m`. For example, if the file did not change
|
||||
from `$orig` to `HEAD` nor `$target`, or if the file changed
|
||||
from `$orig` to `HEAD` and `$orig` to `$target` the same way,
|
||||
obviously the final outcome is what is in `HEAD`. What the
|
||||
@ -4011,20 +4011,20 @@ $ mv -f hello.c~2 hello.c
|
||||
$ git update-index hello.c
|
||||
-------------------------------------------------
|
||||
|
||||
When a path is in the "unmerged" state, running `git-update-index` for
|
||||
When a path is in the "unmerged" state, running `git update-index` for
|
||||
that path tells git to mark the path resolved.
|
||||
|
||||
The above is the description of a git merge at the lowest level,
|
||||
to help you understand what conceptually happens under the hood.
|
||||
In practice, nobody, not even git itself, runs `git-cat-file` three times
|
||||
for this. There is a `git-merge-index` program that extracts the
|
||||
In practice, nobody, not even git itself, runs `git cat-file` three times
|
||||
for this. There is a `git merge-index` program that extracts the
|
||||
stages to temporary files and calls a "merge" script on it:
|
||||
|
||||
-------------------------------------------------
|
||||
$ git merge-index git-merge-one-file hello.c
|
||||
-------------------------------------------------
|
||||
|
||||
and that is what higher level `git-merge -s resolve` is implemented with.
|
||||
and that is what higher level `git merge -s resolve` is implemented with.
|
||||
|
||||
[[hacking-git]]
|
||||
Hacking git
|
||||
@ -4045,12 +4045,12 @@ objects). There are currently four different object types: "blob",
|
||||
Regardless of object type, all objects share the following
|
||||
characteristics: they are all deflated with zlib, and have a header
|
||||
that not only specifies their type, but also provides size information
|
||||
about the data in the object. It's worth noting that the SHA1 hash
|
||||
about the data in the object. It's worth noting that the SHA-1 hash
|
||||
that is used to name the object is the hash of the original data
|
||||
plus this header, so `sha1sum` 'file' does not match the object name
|
||||
for 'file'.
|
||||
(Historical note: in the dawn of the age of git the hash
|
||||
was the sha1 of the 'compressed' object.)
|
||||
was the SHA-1 of the 'compressed' object.)
|
||||
|
||||
As a result, the general consistency of an object can always be tested
|
||||
independently of the contents or the type of the object: all objects can
|
||||
@ -4061,7 +4061,7 @@ size> {plus} <byte\0> {plus} <binary object data>.
|
||||
|
||||
The structured objects can further have their structure and
|
||||
connectivity to other objects verified. This is generally done with
|
||||
the `git-fsck` program, which generates a full dependency graph
|
||||
the `git fsck` program, which generates a full dependency graph
|
||||
of all objects, and verifies their internal consistency (in addition
|
||||
to just verifying their superficial consistency through the hash).
|
||||
|
||||
@ -4120,7 +4120,7 @@ functions like `get_sha1_basic()` or the likes.
|
||||
This is just to get you into the groove for the most libified part of Git:
|
||||
the revision walker.
|
||||
|
||||
Basically, the initial version of `git-log` was a shell script:
|
||||
Basically, the initial version of `git log` was a shell script:
|
||||
|
||||
----------------------------------------------------------------
|
||||
$ git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | \
|
||||
@ -4129,20 +4129,20 @@ $ git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | \
|
||||
|
||||
What does this mean?
|
||||
|
||||
`git-rev-list` is the original version of the revision walker, which
|
||||
`git rev-list` is the original version of the revision walker, which
|
||||
_always_ printed a list of revisions to stdout. It is still functional,
|
||||
and needs to, since most new Git programs start out as scripts using
|
||||
`git-rev-list`.
|
||||
`git rev-list`.
|
||||
|
||||
`git-rev-parse` is not as important any more; it was only used to filter out
|
||||
`git rev-parse` is not as important any more; it was only used to filter out
|
||||
options that were relevant for the different plumbing commands that were
|
||||
called by the script.
|
||||
|
||||
Most of what `git-rev-list` did is contained in `revision.c` and
|
||||
Most of what `git rev-list` did is contained in `revision.c` and
|
||||
`revision.h`. It wraps the options in a struct named `rev_info`, which
|
||||
controls how and what revisions are walked, and more.
|
||||
|
||||
The original job of `git-rev-parse` is now taken by the function
|
||||
The original job of `git rev-parse` is now taken by the function
|
||||
`setup_revisions()`, which parses the revisions and the common command line
|
||||
options for the revision walker. This information is stored in the struct
|
||||
`rev_info` for later consumption. You can do your own command line option
|
||||
@ -4155,7 +4155,7 @@ just have a look at the first implementation of `cmd_log()`; call
|
||||
`git show v1.3.0{tilde}155^2{tilde}4` and scroll down to that function (note that you
|
||||
no longer need to call `setup_pager()` directly).
|
||||
|
||||
Nowadays, `git-log` is a builtin, which means that it is _contained_ in the
|
||||
Nowadays, `git log` is a builtin, which means that it is _contained_ in the
|
||||
command `git`. The source side of a builtin is
|
||||
|
||||
- a function called `cmd_<bla>`, typically defined in `builtin-<bla>.c`,
|
||||
@ -4171,7 +4171,7 @@ since they share quite a bit of code. In that case, the commands which are
|
||||
_not_ named like the `.c` file in which they live have to be listed in
|
||||
`BUILT_INS` in the `Makefile`.
|
||||
|
||||
`git-log` looks more complicated in C than it does in the original script,
|
||||
`git log` looks more complicated in C than it does in the original script,
|
||||
but that allows for a much greater flexibility and performance.
|
||||
|
||||
Here again it is a good point to take a pause.
|
||||
@ -4182,9 +4182,9 @@ the organization of Git (after you know the basic concepts).
|
||||
So, think about something which you are interested in, say, "how can I
|
||||
access a blob just knowing the object name of it?". The first step is to
|
||||
find a Git command with which you can do it. In this example, it is either
|
||||
`git-show` or `git-cat-file`.
|
||||
`git show` or `git cat-file`.
|
||||
|
||||
For the sake of clarity, let's stay with `git-cat-file`, because it
|
||||
For the sake of clarity, let's stay with `git cat-file`, because it
|
||||
|
||||
- is plumbing, and
|
||||
|
||||
@ -4198,7 +4198,7 @@ it does.
|
||||
------------------------------------------------------------------
|
||||
git_config(git_default_config);
|
||||
if (argc != 3)
|
||||
usage("git-cat-file [-t|-s|-e|-p|<type>] <sha1>");
|
||||
usage("git cat-file [-t|-s|-e|-p|<type>] <sha1>");
|
||||
if (get_sha1(argv[2], sha1))
|
||||
die("Not a valid object name %s", argv[2]);
|
||||
------------------------------------------------------------------
|
||||
@ -4243,10 +4243,10 @@ To find out how the result can be used, just read on in `cmd_cat_file()`:
|
||||
-----------------------------------
|
||||
|
||||
Sometimes, you do not know where to look for a feature. In many such cases,
|
||||
it helps to search through the output of `git log`, and then `git-show` the
|
||||
it helps to search through the output of `git log`, and then `git show` the
|
||||
corresponding commit.
|
||||
|
||||
Example: If you know that there was some test case for `git-bundle`, but
|
||||
Example: If you know that there was some test case for `git bundle`, but
|
||||
do not remember where it was (yes, you _could_ `git grep bundle t/`, but that
|
||||
does not illustrate the point!):
|
||||
|
||||
@ -4530,7 +4530,7 @@ The basic requirements:
|
||||
- Whenever possible, section headings should clearly describe the task
|
||||
they explain how to do, in language that requires no more knowledge
|
||||
than necessary: for example, "importing patches into a project" rather
|
||||
than "the git-am command"
|
||||
than "the `git am` command"
|
||||
|
||||
Think about how to create a clear chapter dependency graph that will
|
||||
allow people to get to important topics without necessarily reading
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v1.6.2.1
|
||||
DEF_VER=v1.6.2.GIT
|
||||
|
||||
LF='
|
||||
'
|
||||
|
94
Makefile
94
Makefile
@ -126,6 +126,12 @@ all::
|
||||
# randomly break unless your underlying filesystem supports those sub-second
|
||||
# times (my ext3 doesn't).
|
||||
#
|
||||
# Define USE_ST_TIMESPEC if your "struct stat" uses "st_ctimespec" instead of
|
||||
# "st_ctim"
|
||||
#
|
||||
# Define NO_NSEC if your "struct stat" does not have "st_ctim.tv_nsec"
|
||||
# available. This automatically turns USE_NSEC off.
|
||||
#
|
||||
# Define USE_STDEV below if you want git to care about the underlying device
|
||||
# change being considered an inode change from the update-index perspective.
|
||||
#
|
||||
@ -139,6 +145,8 @@ all::
|
||||
# Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's
|
||||
# MakeMaker (e.g. using ActiveState under Cygwin).
|
||||
#
|
||||
# Define NO_PERL if you do not want Perl scripts or libraries at all.
|
||||
#
|
||||
# Define NO_TCLTK if you do not want Tcl/Tk GUI.
|
||||
#
|
||||
# The TCL_PATH variable governs the location of the Tcl interpreter
|
||||
@ -257,6 +265,18 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
|
||||
BASIC_CFLAGS =
|
||||
BASIC_LDFLAGS =
|
||||
|
||||
# Guard against environment variables
|
||||
BUILTIN_OBJS =
|
||||
BUILT_INS =
|
||||
COMPAT_CFLAGS =
|
||||
COMPAT_OBJS =
|
||||
LIB_H =
|
||||
LIB_OBJS =
|
||||
PROGRAMS =
|
||||
SCRIPT_PERL =
|
||||
SCRIPT_SH =
|
||||
TEST_PROGRAMS =
|
||||
|
||||
SCRIPT_SH += git-am.sh
|
||||
SCRIPT_SH += git-bisect.sh
|
||||
SCRIPT_SH += git-filter-branch.sh
|
||||
@ -335,7 +355,10 @@ BUILT_INS += git-whatchanged$X
|
||||
ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
|
||||
|
||||
# what 'all' will build but not install in gitexecdir
|
||||
OTHER_PROGRAMS = git$X gitweb/gitweb.cgi
|
||||
OTHER_PROGRAMS = git$X
|
||||
ifndef NO_PERL
|
||||
OTHER_PROGRAMS += gitweb/gitweb.cgi
|
||||
endif
|
||||
|
||||
# Set paths to tools early so that they can be used for version tests.
|
||||
ifndef SHELL_PATH
|
||||
@ -414,6 +437,7 @@ LIB_OBJS += archive-tar.o
|
||||
LIB_OBJS += archive-zip.o
|
||||
LIB_OBJS += attr.o
|
||||
LIB_OBJS += base85.o
|
||||
LIB_OBJS += bisect.o
|
||||
LIB_OBJS += blob.o
|
||||
LIB_OBJS += branch.o
|
||||
LIB_OBJS += bundle.o
|
||||
@ -514,6 +538,7 @@ BUILTIN_OBJS += builtin-add.o
|
||||
BUILTIN_OBJS += builtin-annotate.o
|
||||
BUILTIN_OBJS += builtin-apply.o
|
||||
BUILTIN_OBJS += builtin-archive.o
|
||||
BUILTIN_OBJS += builtin-bisect--helper.o
|
||||
BUILTIN_OBJS += builtin-blame.o
|
||||
BUILTIN_OBJS += builtin-branch.o
|
||||
BUILTIN_OBJS += builtin-bundle.o
|
||||
@ -657,6 +682,7 @@ ifeq ($(uname_S),Darwin)
|
||||
endif
|
||||
NO_MEMMEM = YesPlease
|
||||
THREADED_DELTA_SEARCH = YesPlease
|
||||
USE_ST_TIMESPEC = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),SunOS)
|
||||
NEEDS_SOCKET = YesPlease
|
||||
@ -706,6 +732,7 @@ ifeq ($(uname_S),FreeBSD)
|
||||
BASIC_CFLAGS += -I/usr/local/include
|
||||
BASIC_LDFLAGS += -L/usr/local/lib
|
||||
DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
|
||||
USE_ST_TIMESPEC = YesPlease
|
||||
THREADED_DELTA_SEARCH = YesPlease
|
||||
ifeq ($(shell expr "$(uname_R)" : '4\.'),2)
|
||||
PTHREAD_LIBS = -pthread
|
||||
@ -734,6 +761,7 @@ ifeq ($(uname_S),AIX)
|
||||
NO_MEMMEM = YesPlease
|
||||
NO_MKDTEMP = YesPlease
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_NSEC = YesPlease
|
||||
FREAD_READS_DIRECTORIES = UnfortunatelyYes
|
||||
INTERNAL_QSORT = UnfortunatelyYes
|
||||
NEEDS_LIBICONV=YesPlease
|
||||
@ -776,7 +804,6 @@ ifneq (,$(findstring CYGWIN,$(uname_S)))
|
||||
COMPAT_OBJS += compat/cygwin.o
|
||||
endif
|
||||
ifneq (,$(findstring MINGW,$(uname_S)))
|
||||
NO_MMAP = YesPlease
|
||||
NO_PREAD = YesPlease
|
||||
NO_OPENSSL = YesPlease
|
||||
NO_CURL = YesPlease
|
||||
@ -799,6 +826,8 @@ ifneq (,$(findstring MINGW,$(uname_S)))
|
||||
RUNTIME_PREFIX = YesPlease
|
||||
NO_POSIX_ONLY_PROGRAMS = YesPlease
|
||||
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
|
||||
NO_NSEC = YesPlease
|
||||
USE_WIN32_MMAP = YesPlease
|
||||
COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
|
||||
COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
|
||||
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
|
||||
@ -920,6 +949,15 @@ endif
|
||||
ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
|
||||
BASIC_CFLAGS += -DNO_ST_BLOCKS_IN_STRUCT_STAT
|
||||
endif
|
||||
ifdef USE_NSEC
|
||||
BASIC_CFLAGS += -DUSE_NSEC
|
||||
endif
|
||||
ifdef USE_ST_TIMESPEC
|
||||
BASIC_CFLAGS += -DUSE_ST_TIMESPEC
|
||||
endif
|
||||
ifdef NO_NSEC
|
||||
BASIC_CFLAGS += -DNO_NSEC
|
||||
endif
|
||||
ifdef NO_C99_FORMAT
|
||||
BASIC_CFLAGS += -DNO_C99_FORMAT
|
||||
endif
|
||||
@ -967,6 +1005,11 @@ endif
|
||||
ifdef NO_MMAP
|
||||
COMPAT_CFLAGS += -DNO_MMAP
|
||||
COMPAT_OBJS += compat/mmap.o
|
||||
else
|
||||
ifdef USE_WIN32_MMAP
|
||||
COMPAT_CFLAGS += -DUSE_WIN32_MMAP
|
||||
COMPAT_OBJS += compat/win32mmap.o
|
||||
endif
|
||||
endif
|
||||
ifdef NO_PREAD
|
||||
COMPAT_CFLAGS += -DNO_PREAD
|
||||
@ -1068,6 +1111,10 @@ ifeq ($(TCLTK_PATH),)
|
||||
NO_TCLTK=NoThanks
|
||||
endif
|
||||
|
||||
ifeq ($(PERL_PATH),)
|
||||
NO_PERL=NoThanks
|
||||
endif
|
||||
|
||||
QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
|
||||
QUIET_SUBDIR1 =
|
||||
|
||||
@ -1142,7 +1189,9 @@ ifndef NO_TCLTK
|
||||
$(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) gitexecdir='$(gitexec_instdir_SQ)' all
|
||||
$(QUIET_SUBDIR0)gitk-git $(QUIET_SUBDIR1) all
|
||||
endif
|
||||
ifndef NO_PERL
|
||||
$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
|
||||
endif
|
||||
$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1)
|
||||
|
||||
please_set_SHELL_PATH_to_a_more_modern_shell:
|
||||
@ -1155,6 +1204,7 @@ strip: $(PROGRAMS) git$X
|
||||
|
||||
git.o: git.c common-cmds.h GIT-CFLAGS
|
||||
$(QUIET_CC)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
|
||||
'-DGIT_HTML_PATH="$(htmldir_SQ)"' \
|
||||
$(ALL_CFLAGS) -c $(filter %.c,$^)
|
||||
|
||||
git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)
|
||||
@ -1189,6 +1239,7 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
|
||||
chmod +x $@+ && \
|
||||
mv $@+ $@
|
||||
|
||||
ifndef NO_PERL
|
||||
$(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak
|
||||
|
||||
perl/perl.mak: GIT-CFLAGS perl/Makefile perl/Makefile.PL
|
||||
@ -1248,6 +1299,15 @@ git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css
|
||||
$@.sh > $@+ && \
|
||||
chmod +x $@+ && \
|
||||
mv $@+ $@
|
||||
else # NO_PERL
|
||||
$(patsubst %.perl,%,$(SCRIPT_PERL)) git-instaweb: % : unimplemented.sh
|
||||
$(QUIET_GEN)$(RM) $@ $@+ && \
|
||||
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
|
||||
-e 's|@@REASON@@|NO_PERL=$(NO_PERL)|g' \
|
||||
unimplemented.sh >$@+ && \
|
||||
chmod +x $@+ && \
|
||||
mv $@+ $@
|
||||
endif # NO_PERL
|
||||
|
||||
configure: configure.ac
|
||||
$(QUIET_GEN)$(RM) $@ $<+ && \
|
||||
@ -1363,6 +1423,8 @@ GIT-CFLAGS: .FORCE-GIT-CFLAGS
|
||||
GIT-BUILD-OPTIONS: .FORCE-GIT-BUILD-OPTIONS
|
||||
@echo SHELL_PATH=\''$(subst ','\'',$(SHELL_PATH_SQ))'\' >$@
|
||||
@echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@
|
||||
@echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@
|
||||
@echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@
|
||||
|
||||
### Detect Tck/Tk interpreter path changes
|
||||
ifndef NO_TCLTK
|
||||
@ -1565,9 +1627,11 @@ clean:
|
||||
$(RM) -r $(GIT_TARNAME) .doc-tmp-dir
|
||||
$(RM) $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
|
||||
$(RM) $(htmldocs).tar.gz $(manpages).tar.gz
|
||||
$(RM) gitweb/gitweb.cgi
|
||||
$(MAKE) -C Documentation/ clean
|
||||
ifndef NO_PERL
|
||||
$(RM) gitweb/gitweb.cgi
|
||||
$(MAKE) -C perl clean
|
||||
endif
|
||||
$(MAKE) -C templates/ clean
|
||||
$(MAKE) -C t/ clean
|
||||
ifndef NO_TCLTK
|
||||
@ -1640,3 +1704,27 @@ check-docs::
|
||||
check-builtins::
|
||||
./check-builtins.sh
|
||||
|
||||
### Test suite coverage testing
|
||||
#
|
||||
.PHONY: coverage coverage-clean coverage-build coverage-report
|
||||
|
||||
coverage:
|
||||
$(MAKE) coverage-build
|
||||
$(MAKE) coverage-report
|
||||
|
||||
coverage-clean:
|
||||
rm -f *.gcda *.gcno
|
||||
|
||||
COVERAGE_CFLAGS = $(CFLAGS) -O0 -ftest-coverage -fprofile-arcs
|
||||
COVERAGE_LDFLAGS = $(CFLAGS) -O0 -lgcov
|
||||
|
||||
coverage-build: coverage-clean
|
||||
$(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" all
|
||||
$(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" \
|
||||
-j1 test
|
||||
|
||||
coverage-report:
|
||||
gcov -b *.c
|
||||
grep '^function.*called 0 ' *.c.gcov \
|
||||
| sed -e 's/\([^:]*\)\.gcov: *function \([^ ]*\) called.*/\1: \2/' \
|
||||
| tee coverage-untested-functions
|
||||
|
@ -253,6 +253,7 @@ static int parse_archive_args(int argc, const char **argv,
|
||||
const char *base = NULL;
|
||||
const char *remote = NULL;
|
||||
const char *exec = NULL;
|
||||
const char *output = NULL;
|
||||
int compression_level = -1;
|
||||
int verbose = 0;
|
||||
int i;
|
||||
@ -262,6 +263,8 @@ static int parse_archive_args(int argc, const char **argv,
|
||||
OPT_STRING(0, "format", &format, "fmt", "archive format"),
|
||||
OPT_STRING(0, "prefix", &base, "prefix",
|
||||
"prepend prefix to each pathname in the archive"),
|
||||
OPT_STRING(0, "output", &output, "file",
|
||||
"write the archive to this file"),
|
||||
OPT__VERBOSE(&verbose),
|
||||
OPT__COMPR('0', &compression_level, "store only", 0),
|
||||
OPT__COMPR('1', &compression_level, "compress faster", 1),
|
||||
@ -290,6 +293,8 @@ static int parse_archive_args(int argc, const char **argv,
|
||||
die("Unexpected option --remote");
|
||||
if (exec)
|
||||
die("Option --exec can only be used together with --remote");
|
||||
if (output)
|
||||
die("Unexpected option --output");
|
||||
|
||||
if (!base)
|
||||
base = "";
|
||||
|
73
attr.c
73
attr.c
@ -1,3 +1,4 @@
|
||||
#define NO_THE_INDEX_COMPATIBILITY_MACROS
|
||||
#include "cache.h"
|
||||
#include "attr.h"
|
||||
|
||||
@ -318,6 +319,9 @@ static struct attr_stack *read_attr_from_array(const char **list)
|
||||
return res;
|
||||
}
|
||||
|
||||
static enum git_attr_direction direction;
|
||||
static struct index_state *use_index;
|
||||
|
||||
static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
|
||||
{
|
||||
FILE *fp = fopen(path, "r");
|
||||
@ -340,9 +344,10 @@ static void *read_index_data(const char *path)
|
||||
unsigned long sz;
|
||||
enum object_type type;
|
||||
void *data;
|
||||
struct index_state *istate = use_index ? use_index : &the_index;
|
||||
|
||||
len = strlen(path);
|
||||
pos = cache_name_pos(path, len);
|
||||
pos = index_name_pos(istate, path, len);
|
||||
if (pos < 0) {
|
||||
/*
|
||||
* We might be in the middle of a merge, in which
|
||||
@ -350,15 +355,15 @@ static void *read_index_data(const char *path)
|
||||
*/
|
||||
int i;
|
||||
for (i = -pos - 1;
|
||||
(pos < 0 && i < active_nr &&
|
||||
!strcmp(active_cache[i]->name, path));
|
||||
(pos < 0 && i < istate->cache_nr &&
|
||||
!strcmp(istate->cache[i]->name, path));
|
||||
i++)
|
||||
if (ce_stage(active_cache[i]) == 2)
|
||||
if (ce_stage(istate->cache[i]) == 2)
|
||||
pos = i;
|
||||
}
|
||||
if (pos < 0)
|
||||
return NULL;
|
||||
data = read_sha1_file(active_cache[pos]->sha1, &type, &sz);
|
||||
data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
|
||||
if (!data || type != OBJ_BLOB) {
|
||||
free(data);
|
||||
return NULL;
|
||||
@ -366,27 +371,17 @@ static void *read_index_data(const char *path)
|
||||
return data;
|
||||
}
|
||||
|
||||
static struct attr_stack *read_attr(const char *path, int macro_ok)
|
||||
static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
|
||||
{
|
||||
struct attr_stack *res;
|
||||
char *buf, *sp;
|
||||
int lineno = 0;
|
||||
|
||||
res = read_attr_from_file(path, macro_ok);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = xcalloc(1, sizeof(*res));
|
||||
|
||||
/*
|
||||
* There is no checked out .gitattributes file there, but
|
||||
* we might have it in the index. We allow operation in a
|
||||
* sparsely checked out work tree, so read from it.
|
||||
*/
|
||||
buf = read_index_data(path);
|
||||
if (!buf)
|
||||
return res;
|
||||
return NULL;
|
||||
|
||||
res = xcalloc(1, sizeof(*res));
|
||||
for (sp = buf; *sp; ) {
|
||||
char *ep;
|
||||
int more;
|
||||
@ -401,6 +396,30 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct attr_stack *read_attr(const char *path, int macro_ok)
|
||||
{
|
||||
struct attr_stack *res;
|
||||
|
||||
if (direction == GIT_ATTR_CHECKOUT) {
|
||||
res = read_attr_from_index(path, macro_ok);
|
||||
if (!res)
|
||||
res = read_attr_from_file(path, macro_ok);
|
||||
}
|
||||
else {
|
||||
res = read_attr_from_file(path, macro_ok);
|
||||
if (!res)
|
||||
/*
|
||||
* There is no checked out .gitattributes file there, but
|
||||
* we might have it in the index. We allow operation in a
|
||||
* sparsely checked out work tree, so read from it.
|
||||
*/
|
||||
res = read_attr_from_index(path, macro_ok);
|
||||
}
|
||||
if (!res)
|
||||
res = xcalloc(1, sizeof(*res));
|
||||
return res;
|
||||
}
|
||||
|
||||
#if DEBUG_ATTR
|
||||
static void debug_info(const char *what, struct attr_stack *elem)
|
||||
{
|
||||
@ -428,6 +447,15 @@ static void debug_set(const char *what, const char *match, struct git_attr *attr
|
||||
#define debug_set(a,b,c,d) do { ; } while (0)
|
||||
#endif
|
||||
|
||||
static void drop_attr_stack(void)
|
||||
{
|
||||
while (attr_stack) {
|
||||
struct attr_stack *elem = attr_stack;
|
||||
attr_stack = elem->prev;
|
||||
free_attr_elem(elem);
|
||||
}
|
||||
}
|
||||
|
||||
static void bootstrap_attr_stack(void)
|
||||
{
|
||||
if (!attr_stack) {
|
||||
@ -642,3 +670,12 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)
|
||||
{
|
||||
enum git_attr_direction old = direction;
|
||||
direction = new;
|
||||
if (new != old)
|
||||
drop_attr_stack();
|
||||
use_index = istate;
|
||||
}
|
||||
|
6
attr.h
6
attr.h
@ -31,4 +31,10 @@ struct git_attr_check {
|
||||
|
||||
int git_checkattr(const char *path, int, struct git_attr_check *);
|
||||
|
||||
enum git_attr_direction {
|
||||
GIT_ATTR_CHECKIN,
|
||||
GIT_ATTR_CHECKOUT
|
||||
};
|
||||
void git_attr_set_direction(enum git_attr_direction, struct index_state *);
|
||||
|
||||
#endif /* ATTR_H */
|
||||
|
556
bisect.c
Normal file
556
bisect.c
Normal file
@ -0,0 +1,556 @@
|
||||
#include "cache.h"
|
||||
#include "commit.h"
|
||||
#include "diff.h"
|
||||
#include "revision.h"
|
||||
#include "refs.h"
|
||||
#include "list-objects.h"
|
||||
#include "quote.h"
|
||||
#include "sha1-lookup.h"
|
||||
#include "bisect.h"
|
||||
|
||||
static unsigned char (*skipped_sha1)[20];
|
||||
static int skipped_sha1_nr;
|
||||
static int skipped_sha1_alloc;
|
||||
|
||||
static const char **rev_argv;
|
||||
static int rev_argv_nr;
|
||||
static int rev_argv_alloc;
|
||||
|
||||
/* bits #0-15 in revision.h */
|
||||
|
||||
#define COUNTED (1u<<16)
|
||||
|
||||
/*
|
||||
* This is a truly stupid algorithm, but it's only
|
||||
* used for bisection, and we just don't care enough.
|
||||
*
|
||||
* We care just barely enough to avoid recursing for
|
||||
* non-merge entries.
|
||||
*/
|
||||
static int count_distance(struct commit_list *entry)
|
||||
{
|
||||
int nr = 0;
|
||||
|
||||
while (entry) {
|
||||
struct commit *commit = entry->item;
|
||||
struct commit_list *p;
|
||||
|
||||
if (commit->object.flags & (UNINTERESTING | COUNTED))
|
||||
break;
|
||||
if (!(commit->object.flags & TREESAME))
|
||||
nr++;
|
||||
commit->object.flags |= COUNTED;
|
||||
p = commit->parents;
|
||||
entry = p;
|
||||
if (p) {
|
||||
p = p->next;
|
||||
while (p) {
|
||||
nr += count_distance(p);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
static void clear_distance(struct commit_list *list)
|
||||
{
|
||||
while (list) {
|
||||
struct commit *commit = list->item;
|
||||
commit->object.flags &= ~COUNTED;
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
#define DEBUG_BISECT 0
|
||||
|
||||
static inline int weight(struct commit_list *elem)
|
||||
{
|
||||
return *((int*)(elem->item->util));
|
||||
}
|
||||
|
||||
static inline void weight_set(struct commit_list *elem, int weight)
|
||||
{
|
||||
*((int*)(elem->item->util)) = weight;
|
||||
}
|
||||
|
||||
static int count_interesting_parents(struct commit *commit)
|
||||
{
|
||||
struct commit_list *p;
|
||||
int count;
|
||||
|
||||
for (count = 0, p = commit->parents; p; p = p->next) {
|
||||
if (p->item->object.flags & UNINTERESTING)
|
||||
continue;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static inline int halfway(struct commit_list *p, int nr)
|
||||
{
|
||||
/*
|
||||
* Don't short-cut something we are not going to return!
|
||||
*/
|
||||
if (p->item->object.flags & TREESAME)
|
||||
return 0;
|
||||
if (DEBUG_BISECT)
|
||||
return 0;
|
||||
/*
|
||||
* 2 and 3 are halfway of 5.
|
||||
* 3 is halfway of 6 but 2 and 4 are not.
|
||||
*/
|
||||
switch (2 * weight(p) - nr) {
|
||||
case -1: case 0: case 1:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if !DEBUG_BISECT
|
||||
#define show_list(a,b,c,d) do { ; } while (0)
|
||||
#else
|
||||
static void show_list(const char *debug, int counted, int nr,
|
||||
struct commit_list *list)
|
||||
{
|
||||
struct commit_list *p;
|
||||
|
||||
fprintf(stderr, "%s (%d/%d)\n", debug, counted, nr);
|
||||
|
||||
for (p = list; p; p = p->next) {
|
||||
struct commit_list *pp;
|
||||
struct commit *commit = p->item;
|
||||
unsigned flags = commit->object.flags;
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
char *buf = read_sha1_file(commit->object.sha1, &type, &size);
|
||||
char *ep, *sp;
|
||||
|
||||
fprintf(stderr, "%c%c%c ",
|
||||
(flags & TREESAME) ? ' ' : 'T',
|
||||
(flags & UNINTERESTING) ? 'U' : ' ',
|
||||
(flags & COUNTED) ? 'C' : ' ');
|
||||
if (commit->util)
|
||||
fprintf(stderr, "%3d", weight(p));
|
||||
else
|
||||
fprintf(stderr, "---");
|
||||
fprintf(stderr, " %.*s", 8, sha1_to_hex(commit->object.sha1));
|
||||
for (pp = commit->parents; pp; pp = pp->next)
|
||||
fprintf(stderr, " %.*s", 8,
|
||||
sha1_to_hex(pp->item->object.sha1));
|
||||
|
||||
sp = strstr(buf, "\n\n");
|
||||
if (sp) {
|
||||
sp += 2;
|
||||
for (ep = sp; *ep && *ep != '\n'; ep++)
|
||||
;
|
||||
fprintf(stderr, " %.*s", (int)(ep - sp), sp);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG_BISECT */
|
||||
|
||||
static struct commit_list *best_bisection(struct commit_list *list, int nr)
|
||||
{
|
||||
struct commit_list *p, *best;
|
||||
int best_distance = -1;
|
||||
|
||||
best = list;
|
||||
for (p = list; p; p = p->next) {
|
||||
int distance;
|
||||
unsigned flags = p->item->object.flags;
|
||||
|
||||
if (flags & TREESAME)
|
||||
continue;
|
||||
distance = weight(p);
|
||||
if (nr - distance < distance)
|
||||
distance = nr - distance;
|
||||
if (distance > best_distance) {
|
||||
best = p;
|
||||
best_distance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
struct commit_dist {
|
||||
struct commit *commit;
|
||||
int distance;
|
||||
};
|
||||
|
||||
static int compare_commit_dist(const void *a_, const void *b_)
|
||||
{
|
||||
struct commit_dist *a, *b;
|
||||
|
||||
a = (struct commit_dist *)a_;
|
||||
b = (struct commit_dist *)b_;
|
||||
if (a->distance != b->distance)
|
||||
return b->distance - a->distance; /* desc sort */
|
||||
return hashcmp(a->commit->object.sha1, b->commit->object.sha1);
|
||||
}
|
||||
|
||||
static struct commit_list *best_bisection_sorted(struct commit_list *list, int nr)
|
||||
{
|
||||
struct commit_list *p;
|
||||
struct commit_dist *array = xcalloc(nr, sizeof(*array));
|
||||
int cnt, i;
|
||||
|
||||
for (p = list, cnt = 0; p; p = p->next) {
|
||||
int distance;
|
||||
unsigned flags = p->item->object.flags;
|
||||
|
||||
if (flags & TREESAME)
|
||||
continue;
|
||||
distance = weight(p);
|
||||
if (nr - distance < distance)
|
||||
distance = nr - distance;
|
||||
array[cnt].commit = p->item;
|
||||
array[cnt].distance = distance;
|
||||
cnt++;
|
||||
}
|
||||
qsort(array, cnt, sizeof(*array), compare_commit_dist);
|
||||
for (p = list, i = 0; i < cnt; i++) {
|
||||
struct name_decoration *r = xmalloc(sizeof(*r) + 100);
|
||||
struct object *obj = &(array[i].commit->object);
|
||||
|
||||
sprintf(r->name, "dist=%d", array[i].distance);
|
||||
r->next = add_decoration(&name_decoration, obj, r);
|
||||
p->item = array[i].commit;
|
||||
p = p->next;
|
||||
}
|
||||
if (p)
|
||||
p->next = NULL;
|
||||
free(array);
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* zero or positive weight is the number of interesting commits it can
|
||||
* reach, including itself. Especially, weight = 0 means it does not
|
||||
* reach any tree-changing commits (e.g. just above uninteresting one
|
||||
* but traversal is with pathspec).
|
||||
*
|
||||
* weight = -1 means it has one parent and its distance is yet to
|
||||
* be computed.
|
||||
*
|
||||
* weight = -2 means it has more than one parent and its distance is
|
||||
* unknown. After running count_distance() first, they will get zero
|
||||
* or positive distance.
|
||||
*/
|
||||
static struct commit_list *do_find_bisection(struct commit_list *list,
|
||||
int nr, int *weights,
|
||||
int find_all)
|
||||
{
|
||||
int n, counted;
|
||||
struct commit_list *p;
|
||||
|
||||
counted = 0;
|
||||
|
||||
for (n = 0, p = list; p; p = p->next) {
|
||||
struct commit *commit = p->item;
|
||||
unsigned flags = commit->object.flags;
|
||||
|
||||
p->item->util = &weights[n++];
|
||||
switch (count_interesting_parents(commit)) {
|
||||
case 0:
|
||||
if (!(flags & TREESAME)) {
|
||||
weight_set(p, 1);
|
||||
counted++;
|
||||
show_list("bisection 2 count one",
|
||||
counted, nr, list);
|
||||
}
|
||||
/*
|
||||
* otherwise, it is known not to reach any
|
||||
* tree-changing commit and gets weight 0.
|
||||
*/
|
||||
break;
|
||||
case 1:
|
||||
weight_set(p, -1);
|
||||
break;
|
||||
default:
|
||||
weight_set(p, -2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
show_list("bisection 2 initialize", counted, nr, list);
|
||||
|
||||
/*
|
||||
* If you have only one parent in the resulting set
|
||||
* then you can reach one commit more than that parent
|
||||
* can reach. So we do not have to run the expensive
|
||||
* count_distance() for single strand of pearls.
|
||||
*
|
||||
* However, if you have more than one parents, you cannot
|
||||
* just add their distance and one for yourself, since
|
||||
* they usually reach the same ancestor and you would
|
||||
* end up counting them twice that way.
|
||||
*
|
||||
* So we will first count distance of merges the usual
|
||||
* way, and then fill the blanks using cheaper algorithm.
|
||||
*/
|
||||
for (p = list; p; p = p->next) {
|
||||
if (p->item->object.flags & UNINTERESTING)
|
||||
continue;
|
||||
if (weight(p) != -2)
|
||||
continue;
|
||||
weight_set(p, count_distance(p));
|
||||
clear_distance(list);
|
||||
|
||||
/* Does it happen to be at exactly half-way? */
|
||||
if (!find_all && halfway(p, nr))
|
||||
return p;
|
||||
counted++;
|
||||
}
|
||||
|
||||
show_list("bisection 2 count_distance", counted, nr, list);
|
||||
|
||||
while (counted < nr) {
|
||||
for (p = list; p; p = p->next) {
|
||||
struct commit_list *q;
|
||||
unsigned flags = p->item->object.flags;
|
||||
|
||||
if (0 <= weight(p))
|
||||
continue;
|
||||
for (q = p->item->parents; q; q = q->next) {
|
||||
if (q->item->object.flags & UNINTERESTING)
|
||||
continue;
|
||||
if (0 <= weight(q))
|
||||
break;
|
||||
}
|
||||
if (!q)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* weight for p is unknown but q is known.
|
||||
* add one for p itself if p is to be counted,
|
||||
* otherwise inherit it from q directly.
|
||||
*/
|
||||
if (!(flags & TREESAME)) {
|
||||
weight_set(p, weight(q)+1);
|
||||
counted++;
|
||||
show_list("bisection 2 count one",
|
||||
counted, nr, list);
|
||||
}
|
||||
else
|
||||
weight_set(p, weight(q));
|
||||
|
||||
/* Does it happen to be at exactly half-way? */
|
||||
if (!find_all && halfway(p, nr))
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
show_list("bisection 2 counted all", counted, nr, list);
|
||||
|
||||
if (!find_all)
|
||||
return best_bisection(list, nr);
|
||||
else
|
||||
return best_bisection_sorted(list, nr);
|
||||
}
|
||||
|
||||
struct commit_list *find_bisection(struct commit_list *list,
|
||||
int *reaches, int *all,
|
||||
int find_all)
|
||||
{
|
||||
int nr, on_list;
|
||||
struct commit_list *p, *best, *next, *last;
|
||||
int *weights;
|
||||
|
||||
show_list("bisection 2 entry", 0, 0, list);
|
||||
|
||||
/*
|
||||
* Count the number of total and tree-changing items on the
|
||||
* list, while reversing the list.
|
||||
*/
|
||||
for (nr = on_list = 0, last = NULL, p = list;
|
||||
p;
|
||||
p = next) {
|
||||
unsigned flags = p->item->object.flags;
|
||||
|
||||
next = p->next;
|
||||
if (flags & UNINTERESTING)
|
||||
continue;
|
||||
p->next = last;
|
||||
last = p;
|
||||
if (!(flags & TREESAME))
|
||||
nr++;
|
||||
on_list++;
|
||||
}
|
||||
list = last;
|
||||
show_list("bisection 2 sorted", 0, nr, list);
|
||||
|
||||
*all = nr;
|
||||
weights = xcalloc(on_list, sizeof(*weights));
|
||||
|
||||
/* Do the real work of finding bisection commit. */
|
||||
best = do_find_bisection(list, nr, weights, find_all);
|
||||
if (best) {
|
||||
if (!find_all)
|
||||
best->next = NULL;
|
||||
*reaches = weight(best);
|
||||
}
|
||||
free(weights);
|
||||
return best;
|
||||
}
|
||||
|
||||
static int register_ref(const char *refname, const unsigned char *sha1,
|
||||
int flags, void *cb_data)
|
||||
{
|
||||
if (!strcmp(refname, "bad")) {
|
||||
ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
|
||||
rev_argv[rev_argv_nr++] = xstrdup(sha1_to_hex(sha1));
|
||||
} else if (!prefixcmp(refname, "good-")) {
|
||||
const char *hex = sha1_to_hex(sha1);
|
||||
char *good = xmalloc(strlen(hex) + 2);
|
||||
*good = '^';
|
||||
memcpy(good + 1, hex, strlen(hex) + 1);
|
||||
ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
|
||||
rev_argv[rev_argv_nr++] = good;
|
||||
} else if (!prefixcmp(refname, "skip-")) {
|
||||
ALLOC_GROW(skipped_sha1, skipped_sha1_nr + 1,
|
||||
skipped_sha1_alloc);
|
||||
hashcpy(skipped_sha1[skipped_sha1_nr++], sha1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_bisect_refs(void)
|
||||
{
|
||||
return for_each_ref_in("refs/bisect/", register_ref, NULL);
|
||||
}
|
||||
|
||||
void read_bisect_paths(void)
|
||||
{
|
||||
struct strbuf str = STRBUF_INIT;
|
||||
const char *filename = git_path("BISECT_NAMES");
|
||||
FILE *fp = fopen(filename, "r");
|
||||
|
||||
if (!fp)
|
||||
die("Could not open file '%s': %s", filename, strerror(errno));
|
||||
|
||||
while (strbuf_getline(&str, fp, '\n') != EOF) {
|
||||
char *quoted;
|
||||
int res;
|
||||
|
||||
strbuf_trim(&str);
|
||||
quoted = strbuf_detach(&str, NULL);
|
||||
res = sq_dequote_to_argv(quoted, &rev_argv,
|
||||
&rev_argv_nr, &rev_argv_alloc);
|
||||
if (res)
|
||||
die("Badly quoted content in file '%s': %s",
|
||||
filename, quoted);
|
||||
}
|
||||
|
||||
strbuf_release(&str);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static int skipcmp(const void *a, const void *b)
|
||||
{
|
||||
return hashcmp(a, b);
|
||||
}
|
||||
|
||||
static void prepare_skipped(void)
|
||||
{
|
||||
qsort(skipped_sha1, skipped_sha1_nr, sizeof(*skipped_sha1), skipcmp);
|
||||
}
|
||||
|
||||
static const unsigned char *skipped_sha1_access(size_t index, void *table)
|
||||
{
|
||||
unsigned char (*skipped)[20] = table;
|
||||
return skipped[index];
|
||||
}
|
||||
|
||||
static int lookup_skipped(unsigned char *sha1)
|
||||
{
|
||||
return sha1_pos(sha1, skipped_sha1, skipped_sha1_nr,
|
||||
skipped_sha1_access);
|
||||
}
|
||||
|
||||
struct commit_list *filter_skipped(struct commit_list *list,
|
||||
struct commit_list **tried,
|
||||
int show_all)
|
||||
{
|
||||
struct commit_list *filtered = NULL, **f = &filtered;
|
||||
|
||||
*tried = NULL;
|
||||
|
||||
if (!skipped_sha1_nr)
|
||||
return list;
|
||||
|
||||
prepare_skipped();
|
||||
|
||||
while (list) {
|
||||
struct commit_list *next = list->next;
|
||||
list->next = NULL;
|
||||
if (0 <= lookup_skipped(list->item->object.sha1)) {
|
||||
/* Move current to tried list */
|
||||
*tried = list;
|
||||
tried = &list->next;
|
||||
} else {
|
||||
if (!show_all)
|
||||
return list;
|
||||
/* Move current to filtered list */
|
||||
*f = list;
|
||||
f = &list->next;
|
||||
}
|
||||
list = next;
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
static void bisect_rev_setup(struct rev_info *revs, const char *prefix)
|
||||
{
|
||||
init_revisions(revs, prefix);
|
||||
revs->abbrev = 0;
|
||||
revs->commit_format = CMIT_FMT_UNSPECIFIED;
|
||||
|
||||
/* argv[0] will be ignored by setup_revisions */
|
||||
ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
|
||||
rev_argv[rev_argv_nr++] = xstrdup("bisect_rev_setup");
|
||||
|
||||
if (read_bisect_refs())
|
||||
die("reading bisect refs failed");
|
||||
|
||||
ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
|
||||
rev_argv[rev_argv_nr++] = xstrdup("--");
|
||||
|
||||
read_bisect_paths();
|
||||
|
||||
ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
|
||||
rev_argv[rev_argv_nr++] = NULL;
|
||||
|
||||
setup_revisions(rev_argv_nr, rev_argv, revs, NULL);
|
||||
|
||||
revs->limited = 1;
|
||||
}
|
||||
|
||||
int bisect_next_vars(const char *prefix)
|
||||
{
|
||||
struct rev_info revs;
|
||||
struct rev_list_info info;
|
||||
int reaches = 0, all = 0;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.revs = &revs;
|
||||
info.bisect_show_flags = BISECT_SHOW_TRIED | BISECT_SHOW_STRINGED;
|
||||
|
||||
bisect_rev_setup(&revs, prefix);
|
||||
|
||||
if (prepare_revision_walk(&revs))
|
||||
die("revision walk setup failed");
|
||||
if (revs.tree_objects)
|
||||
mark_edges_uninteresting(revs.commits, &revs, NULL);
|
||||
|
||||
revs.commits = find_bisection(revs.commits, &reaches, &all,
|
||||
!!skipped_sha1_nr);
|
||||
|
||||
return show_bisect_vars(&info, reaches, all);
|
||||
}
|
29
bisect.h
Normal file
29
bisect.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef BISECT_H
|
||||
#define BISECT_H
|
||||
|
||||
extern struct commit_list *find_bisection(struct commit_list *list,
|
||||
int *reaches, int *all,
|
||||
int find_all);
|
||||
|
||||
extern struct commit_list *filter_skipped(struct commit_list *list,
|
||||
struct commit_list **tried,
|
||||
int show_all);
|
||||
|
||||
/* bisect_show_flags flags in struct rev_list_info */
|
||||
#define BISECT_SHOW_ALL (1<<0)
|
||||
#define BISECT_SHOW_TRIED (1<<1)
|
||||
#define BISECT_SHOW_STRINGED (1<<2)
|
||||
|
||||
struct rev_list_info {
|
||||
struct rev_info *revs;
|
||||
int bisect_show_flags;
|
||||
int show_timestamp;
|
||||
int hdr_termination;
|
||||
const char *header_prefix;
|
||||
};
|
||||
|
||||
extern int show_bisect_vars(struct rev_list_info *info, int reaches, int all);
|
||||
|
||||
extern int bisect_next_vars(const char *prefix);
|
||||
|
||||
#endif
|
70
branch.c
70
branch.c
@ -32,21 +32,59 @@ static int find_tracked_branch(struct remote *remote, void *priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int should_setup_rebase(const struct tracking *tracking)
|
||||
static int should_setup_rebase(const char *origin)
|
||||
{
|
||||
switch (autorebase) {
|
||||
case AUTOREBASE_NEVER:
|
||||
return 0;
|
||||
case AUTOREBASE_LOCAL:
|
||||
return tracking->remote == NULL;
|
||||
return origin == NULL;
|
||||
case AUTOREBASE_REMOTE:
|
||||
return tracking->remote != NULL;
|
||||
return origin != NULL;
|
||||
case AUTOREBASE_ALWAYS:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
|
||||
{
|
||||
struct strbuf key = STRBUF_INIT;
|
||||
int rebasing = should_setup_rebase(origin);
|
||||
|
||||
strbuf_addf(&key, "branch.%s.remote", local);
|
||||
git_config_set(key.buf, origin ? origin : ".");
|
||||
|
||||
strbuf_reset(&key);
|
||||
strbuf_addf(&key, "branch.%s.merge", local);
|
||||
git_config_set(key.buf, remote);
|
||||
|
||||
if (rebasing) {
|
||||
strbuf_reset(&key);
|
||||
strbuf_addf(&key, "branch.%s.rebase", local);
|
||||
git_config_set(key.buf, "true");
|
||||
}
|
||||
|
||||
if (flag & BRANCH_CONFIG_VERBOSE) {
|
||||
strbuf_reset(&key);
|
||||
|
||||
strbuf_addstr(&key, origin ? "remote" : "local");
|
||||
|
||||
/* Are we tracking a proper "branch"? */
|
||||
if (!prefixcmp(remote, "refs/heads/")) {
|
||||
strbuf_addf(&key, " branch %s", remote + 11);
|
||||
if (origin)
|
||||
strbuf_addf(&key, " from %s", origin);
|
||||
}
|
||||
else
|
||||
strbuf_addf(&key, " ref %s", remote);
|
||||
printf("Branch %s set up to track %s%s.\n",
|
||||
local, key.buf,
|
||||
rebasing ? " by rebasing" : "");
|
||||
}
|
||||
strbuf_release(&key);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called when new_ref is branched off of orig_ref, and tries
|
||||
* to infer the settings for branch.<new_ref>.{remote,merge} from the
|
||||
@ -55,7 +93,6 @@ static int should_setup_rebase(const struct tracking *tracking)
|
||||
static int setup_tracking(const char *new_ref, const char *orig_ref,
|
||||
enum branch_track track)
|
||||
{
|
||||
char key[1024];
|
||||
struct tracking tracking;
|
||||
|
||||
if (strlen(new_ref) > 1024 - 7 - 7 - 1)
|
||||
@ -80,19 +117,10 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
|
||||
return error("Not tracking: ambiguous information for ref %s",
|
||||
orig_ref);
|
||||
|
||||
sprintf(key, "branch.%s.remote", new_ref);
|
||||
git_config_set(key, tracking.remote ? tracking.remote : ".");
|
||||
sprintf(key, "branch.%s.merge", new_ref);
|
||||
git_config_set(key, tracking.src ? tracking.src : orig_ref);
|
||||
printf("Branch %s set up to track %s branch %s.\n", new_ref,
|
||||
tracking.remote ? "remote" : "local", orig_ref);
|
||||
if (should_setup_rebase(&tracking)) {
|
||||
sprintf(key, "branch.%s.rebase", new_ref);
|
||||
git_config_set(key, "true");
|
||||
printf("This branch will rebase on pull.\n");
|
||||
}
|
||||
free(tracking.src);
|
||||
install_branch_config(BRANCH_CONFIG_VERBOSE, new_ref, tracking.remote,
|
||||
tracking.src ? tracking.src : orig_ref);
|
||||
|
||||
free(tracking.src);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -106,16 +134,8 @@ void create_branch(const char *head,
|
||||
char *real_ref, msg[PATH_MAX + 20];
|
||||
struct strbuf ref = STRBUF_INIT;
|
||||
int forcing = 0;
|
||||
int len;
|
||||
|
||||
len = strlen(name);
|
||||
if (interpret_nth_last_branch(name, &ref) != len) {
|
||||
strbuf_reset(&ref);
|
||||
strbuf_add(&ref, name, len);
|
||||
}
|
||||
strbuf_splice(&ref, 0, 0, "refs/heads/", 11);
|
||||
|
||||
if (check_ref_format(ref.buf))
|
||||
if (strbuf_check_branch_ref(&ref, name))
|
||||
die("'%s' is not a valid branch name.", name);
|
||||
|
||||
if (resolve_ref(ref.buf, sha1, 1, NULL)) {
|
||||
|
7
branch.h
7
branch.h
@ -21,4 +21,11 @@ void create_branch(const char *head, const char *name, const char *start_name,
|
||||
*/
|
||||
void remove_branch_state(void);
|
||||
|
||||
/*
|
||||
* Configure local branch "local" to merge remote branch "remote"
|
||||
* taken from origin "origin".
|
||||
*/
|
||||
#define BRANCH_CONFIG_VERBOSE 01
|
||||
extern void install_branch_config(int flag, const char *local, const char *origin, const char *remote);
|
||||
|
||||
#endif
|
||||
|
@ -104,7 +104,7 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec,
|
||||
/* Set up the default git porcelain excludes */
|
||||
memset(dir, 0, sizeof(*dir));
|
||||
if (!ignored_too) {
|
||||
dir->collect_ignored = 1;
|
||||
dir->flags |= DIR_COLLECT_IGNORED;
|
||||
setup_standard_excludes(dir);
|
||||
}
|
||||
|
||||
@ -148,7 +148,7 @@ static const char **validate_pathspec(int argc, const char **argv, const char *p
|
||||
if (pathspec) {
|
||||
const char **p;
|
||||
for (p = pathspec; *p; p++) {
|
||||
if (has_symlink_leading_path(strlen(*p), *p)) {
|
||||
if (has_symlink_leading_path(*p, strlen(*p))) {
|
||||
int len = prefix ? strlen(prefix) : 0;
|
||||
die("'%s' is beyond a symbolic link", *p + len);
|
||||
}
|
||||
|
@ -2360,7 +2360,7 @@ static int check_to_create_blob(const char *new_name, int ok_if_exists)
|
||||
* In such a case, path "new_name" does not exist as
|
||||
* far as git is concerned.
|
||||
*/
|
||||
if (has_symlink_leading_path(strlen(new_name), new_name))
|
||||
if (has_symlink_leading_path(new_name, strlen(new_name)))
|
||||
return 0;
|
||||
|
||||
return error("%s: already exists in working directory", new_name);
|
||||
@ -2451,7 +2451,7 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
|
||||
if ((st_mode ^ patch->old_mode) & S_IFMT)
|
||||
return error("%s: wrong type", old_name);
|
||||
if (st_mode != patch->old_mode)
|
||||
fprintf(stderr, "warning: %s has type %o, expected %o\n",
|
||||
warning("%s has type %o, expected %o",
|
||||
old_name, st_mode, patch->old_mode);
|
||||
if (!patch->new_mode && !patch->is_delete)
|
||||
patch->new_mode = st_mode;
|
||||
@ -2932,8 +2932,7 @@ static int write_out_one_reject(struct patch *patch)
|
||||
cnt = strlen(patch->new_name);
|
||||
if (ARRAY_SIZE(namebuf) <= cnt + 5) {
|
||||
cnt = ARRAY_SIZE(namebuf) - 5;
|
||||
fprintf(stderr,
|
||||
"warning: truncating .rej filename to %.*s.rej",
|
||||
warning("truncating .rej filename to %.*s.rej",
|
||||
cnt - 1, patch->new_name);
|
||||
}
|
||||
memcpy(namebuf, patch->new_name, cnt);
|
||||
@ -3212,7 +3211,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
|
||||
struct option builtin_apply_options[] = {
|
||||
{ OPTION_CALLBACK, 0, "exclude", NULL, "path",
|
||||
"don´t apply changes matching the given path",
|
||||
"don't apply changes matching the given path",
|
||||
0, option_parse_exclude },
|
||||
{ OPTION_CALLBACK, 0, "include", NULL, "path",
|
||||
"apply changes matching the given path",
|
||||
@ -3224,10 +3223,10 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
"ignore additions made by the patch"),
|
||||
OPT_BOOLEAN(0, "stat", &diffstat,
|
||||
"instead of applying the patch, output diffstat for the input"),
|
||||
OPT_BOOLEAN(0, "allow-binary-replacement", &binary,
|
||||
"now no-op"),
|
||||
OPT_BOOLEAN(0, "binary", &binary,
|
||||
"now no-op"),
|
||||
{ OPTION_BOOLEAN, 0, "allow-binary-replacement", &binary,
|
||||
NULL, "old option, now no-op", PARSE_OPT_HIDDEN },
|
||||
{ OPTION_BOOLEAN, 0, "binary", &binary,
|
||||
NULL, "old option, now no-op", PARSE_OPT_HIDDEN },
|
||||
OPT_BOOLEAN(0, "numstat", &numstat,
|
||||
"shows number of added and deleted lines in decimal notation"),
|
||||
OPT_BOOLEAN(0, "summary", &summary,
|
||||
@ -3315,8 +3314,8 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
squelch_whitespace_errors < whitespace_error) {
|
||||
int squelched =
|
||||
whitespace_error - squelch_whitespace_errors;
|
||||
fprintf(stderr, "warning: squelched %d "
|
||||
"whitespace error%s\n",
|
||||
warning("squelched %d "
|
||||
"whitespace error%s",
|
||||
squelched,
|
||||
squelched == 1 ? "" : "s");
|
||||
}
|
||||
@ -3326,12 +3325,12 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
whitespace_error == 1 ? "" : "s",
|
||||
whitespace_error == 1 ? "s" : "");
|
||||
if (applied_after_fixing_ws && apply)
|
||||
fprintf(stderr, "warning: %d line%s applied after"
|
||||
" fixing whitespace errors.\n",
|
||||
warning("%d line%s applied after"
|
||||
" fixing whitespace errors.",
|
||||
applied_after_fixing_ws,
|
||||
applied_after_fixing_ws == 1 ? "" : "s");
|
||||
else if (whitespace_error)
|
||||
fprintf(stderr, "warning: %d line%s add%s whitespace errors.\n",
|
||||
warning("%d line%s add%s whitespace errors.",
|
||||
whitespace_error,
|
||||
whitespace_error == 1 ? "" : "s",
|
||||
whitespace_error == 1 ? "s" : "");
|
||||
|
@ -5,44 +5,35 @@
|
||||
#include "cache.h"
|
||||
#include "builtin.h"
|
||||
#include "archive.h"
|
||||
#include "parse-options.h"
|
||||
#include "pkt-line.h"
|
||||
#include "sideband.h"
|
||||
|
||||
static int run_remote_archiver(const char *remote, int argc,
|
||||
const char **argv)
|
||||
static void create_output_file(const char *output_file)
|
||||
{
|
||||
int output_fd = open(output_file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
|
||||
if (output_fd < 0)
|
||||
die("could not create archive file: %s ", output_file);
|
||||
if (output_fd != 1) {
|
||||
if (dup2(output_fd, 1) < 0)
|
||||
die("could not redirect output");
|
||||
else
|
||||
close(output_fd);
|
||||
}
|
||||
}
|
||||
|
||||
static int run_remote_archiver(int argc, const char **argv,
|
||||
const char *remote, const char *exec)
|
||||
{
|
||||
char *url, buf[LARGE_PACKET_MAX];
|
||||
int fd[2], i, len, rv;
|
||||
struct child_process *conn;
|
||||
const char *exec = "git-upload-archive";
|
||||
int exec_at = 0, exec_value_at = 0;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
if (!prefixcmp(arg, "--exec=")) {
|
||||
if (exec_at)
|
||||
die("multiple --exec specified");
|
||||
exec = arg + 7;
|
||||
exec_at = i;
|
||||
} else if (!strcmp(arg, "--exec")) {
|
||||
if (exec_at)
|
||||
die("multiple --exec specified");
|
||||
if (i + 1 >= argc)
|
||||
die("option --exec requires a value");
|
||||
exec = argv[i + 1];
|
||||
exec_at = i;
|
||||
exec_value_at = ++i;
|
||||
}
|
||||
}
|
||||
|
||||
url = xstrdup(remote);
|
||||
conn = git_connect(fd, url, exec, 0);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (i == exec_at || i == exec_value_at)
|
||||
continue;
|
||||
for (i = 1; i < argc; i++)
|
||||
packet_write(fd[1], "argument %s\n", argv[i]);
|
||||
}
|
||||
packet_flush(fd[1]);
|
||||
|
||||
len = packet_read_line(fd[0], buf, sizeof(buf));
|
||||
@ -61,7 +52,7 @@ static int run_remote_archiver(const char *remote, int argc,
|
||||
die("git archive: expected a flush");
|
||||
|
||||
/* Now, start reading from fd[0] and spit it out to stdout */
|
||||
rv = recv_sideband("archive", fd[0], 1, 2);
|
||||
rv = recv_sideband("archive", fd[0], 1);
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
rv |= finish_connect(conn);
|
||||
@ -69,51 +60,33 @@ static int run_remote_archiver(const char *remote, int argc,
|
||||
return !!rv;
|
||||
}
|
||||
|
||||
static const char *extract_remote_arg(int *ac, const char **av)
|
||||
{
|
||||
int ix, iy, cnt = *ac;
|
||||
int no_more_options = 0;
|
||||
const char *remote = NULL;
|
||||
|
||||
for (ix = iy = 1; ix < cnt; ix++) {
|
||||
const char *arg = av[ix];
|
||||
if (!strcmp(arg, "--"))
|
||||
no_more_options = 1;
|
||||
if (!no_more_options) {
|
||||
if (!prefixcmp(arg, "--remote=")) {
|
||||
if (remote)
|
||||
die("Multiple --remote specified");
|
||||
remote = arg + 9;
|
||||
continue;
|
||||
} else if (!strcmp(arg, "--remote")) {
|
||||
if (remote)
|
||||
die("Multiple --remote specified");
|
||||
if (++ix >= cnt)
|
||||
die("option --remote requires a value");
|
||||
remote = av[ix];
|
||||
continue;
|
||||
}
|
||||
if (arg[0] != '-')
|
||||
no_more_options = 1;
|
||||
}
|
||||
if (ix != iy)
|
||||
av[iy] = arg;
|
||||
iy++;
|
||||
}
|
||||
if (remote) {
|
||||
av[--cnt] = NULL;
|
||||
*ac = cnt;
|
||||
}
|
||||
return remote;
|
||||
}
|
||||
#define PARSE_OPT_KEEP_ALL ( PARSE_OPT_KEEP_DASHDASH | \
|
||||
PARSE_OPT_KEEP_ARGV0 | \
|
||||
PARSE_OPT_KEEP_UNKNOWN | \
|
||||
PARSE_OPT_NO_INTERNAL_HELP )
|
||||
|
||||
int cmd_archive(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
const char *exec = "git-upload-archive";
|
||||
const char *output = NULL;
|
||||
const char *remote = NULL;
|
||||
struct option local_opts[] = {
|
||||
OPT_STRING(0, "output", &output, "file",
|
||||
"write the archive to this file"),
|
||||
OPT_STRING(0, "remote", &remote, "repo",
|
||||
"retrieve the archive from remote repository <repo>"),
|
||||
OPT_STRING(0, "exec", &exec, "cmd",
|
||||
"path to the remote git-upload-archive command"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, local_opts, NULL, PARSE_OPT_KEEP_ALL);
|
||||
|
||||
if (output)
|
||||
create_output_file(output);
|
||||
|
||||
remote = extract_remote_arg(&argc, argv);
|
||||
if (remote)
|
||||
return run_remote_archiver(remote, argc, argv);
|
||||
return run_remote_archiver(argc, argv, remote, exec);
|
||||
|
||||
setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
|
||||
|
||||
|
27
builtin-bisect--helper.c
Normal file
27
builtin-bisect--helper.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "parse-options.h"
|
||||
#include "bisect.h"
|
||||
|
||||
static const char * const git_bisect_helper_usage[] = {
|
||||
"git bisect--helper --next-vars",
|
||||
NULL
|
||||
};
|
||||
|
||||
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int next_vars = 0;
|
||||
struct option options[] = {
|
||||
OPT_BOOLEAN(0, "next-vars", &next_vars,
|
||||
"output next bisect step variables"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, options, git_bisect_helper_usage, 0);
|
||||
|
||||
if (!next_vars)
|
||||
usage_with_options(git_bisect_helper_usage, options);
|
||||
|
||||
/* next-vars */
|
||||
return bisect_next_vars(prefix);
|
||||
}
|
182
builtin-blame.c
182
builtin-blame.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Pickaxe
|
||||
* Blame
|
||||
*
|
||||
* Copyright (c) 2006, Junio C Hamano
|
||||
*/
|
||||
@ -40,6 +40,10 @@ static int reverse;
|
||||
static int blank_boundary;
|
||||
static int incremental;
|
||||
static int xdl_opts = XDF_NEED_MINIMAL;
|
||||
|
||||
static enum date_mode blame_date_mode = DATE_ISO8601;
|
||||
static size_t blame_date_width;
|
||||
|
||||
static struct string_list mailmap;
|
||||
|
||||
#ifndef DEBUG
|
||||
@ -74,6 +78,7 @@ static unsigned blame_copy_score;
|
||||
*/
|
||||
struct origin {
|
||||
int refcnt;
|
||||
struct origin *previous;
|
||||
struct commit *commit;
|
||||
mmfile_t file;
|
||||
unsigned char blob_sha1[20];
|
||||
@ -115,6 +120,8 @@ static inline struct origin *origin_incref(struct origin *o)
|
||||
static void origin_decref(struct origin *o)
|
||||
{
|
||||
if (o && --o->refcnt <= 0) {
|
||||
if (o->previous)
|
||||
origin_decref(o->previous);
|
||||
free(o->file.ptr);
|
||||
free(o);
|
||||
}
|
||||
@ -1198,6 +1205,10 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
|
||||
struct origin *porigin = sg_origin[i];
|
||||
if (!porigin)
|
||||
continue;
|
||||
if (!origin->previous) {
|
||||
origin_incref(porigin);
|
||||
origin->previous = porigin;
|
||||
}
|
||||
if (pass_blame_to_parent(sb, origin, porigin))
|
||||
goto finish;
|
||||
}
|
||||
@ -1414,6 +1425,39 @@ static void write_filename_info(const char *path)
|
||||
write_name_quoted(path, stdout, '\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* Porcelain/Incremental format wants to show a lot of details per
|
||||
* commit. Instead of repeating this every line, emit it only once,
|
||||
* the first time each commit appears in the output.
|
||||
*/
|
||||
static int emit_one_suspect_detail(struct origin *suspect)
|
||||
{
|
||||
struct commit_info ci;
|
||||
|
||||
if (suspect->commit->object.flags & METAINFO_SHOWN)
|
||||
return 0;
|
||||
|
||||
suspect->commit->object.flags |= METAINFO_SHOWN;
|
||||
get_commit_info(suspect->commit, &ci, 1);
|
||||
printf("author %s\n", ci.author);
|
||||
printf("author-mail %s\n", ci.author_mail);
|
||||
printf("author-time %lu\n", ci.author_time);
|
||||
printf("author-tz %s\n", ci.author_tz);
|
||||
printf("committer %s\n", ci.committer);
|
||||
printf("committer-mail %s\n", ci.committer_mail);
|
||||
printf("committer-time %lu\n", ci.committer_time);
|
||||
printf("committer-tz %s\n", ci.committer_tz);
|
||||
printf("summary %s\n", ci.summary);
|
||||
if (suspect->commit->object.flags & UNINTERESTING)
|
||||
printf("boundary\n");
|
||||
if (suspect->previous) {
|
||||
struct origin *prev = suspect->previous;
|
||||
printf("previous %s ", sha1_to_hex(prev->commit->object.sha1));
|
||||
write_name_quoted(prev->path, stdout, '\n');
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The blame_entry is found to be guilty for the range. Mark it
|
||||
* as such, and show it in incremental output.
|
||||
@ -1429,22 +1473,7 @@ static void found_guilty_entry(struct blame_entry *ent)
|
||||
printf("%s %d %d %d\n",
|
||||
sha1_to_hex(suspect->commit->object.sha1),
|
||||
ent->s_lno + 1, ent->lno + 1, ent->num_lines);
|
||||
if (!(suspect->commit->object.flags & METAINFO_SHOWN)) {
|
||||
struct commit_info ci;
|
||||
suspect->commit->object.flags |= METAINFO_SHOWN;
|
||||
get_commit_info(suspect->commit, &ci, 1);
|
||||
printf("author %s\n", ci.author);
|
||||
printf("author-mail %s\n", ci.author_mail);
|
||||
printf("author-time %lu\n", ci.author_time);
|
||||
printf("author-tz %s\n", ci.author_tz);
|
||||
printf("committer %s\n", ci.committer);
|
||||
printf("committer-mail %s\n", ci.committer_mail);
|
||||
printf("committer-time %lu\n", ci.committer_time);
|
||||
printf("committer-tz %s\n", ci.committer_tz);
|
||||
printf("summary %s\n", ci.summary);
|
||||
if (suspect->commit->object.flags & UNINTERESTING)
|
||||
printf("boundary\n");
|
||||
}
|
||||
emit_one_suspect_detail(suspect);
|
||||
write_filename_info(suspect->path);
|
||||
maybe_flush_or_die(stdout, "stdout");
|
||||
}
|
||||
@ -1507,24 +1536,20 @@ static const char *format_time(unsigned long time, const char *tz_str,
|
||||
int show_raw_time)
|
||||
{
|
||||
static char time_buf[128];
|
||||
time_t t = time;
|
||||
int minutes, tz;
|
||||
struct tm *tm;
|
||||
const char *time_str;
|
||||
int time_len;
|
||||
int tz;
|
||||
|
||||
if (show_raw_time) {
|
||||
sprintf(time_buf, "%lu %s", time, tz_str);
|
||||
return time_buf;
|
||||
}
|
||||
|
||||
tz = atoi(tz_str);
|
||||
minutes = tz < 0 ? -tz : tz;
|
||||
minutes = (minutes / 100)*60 + (minutes % 100);
|
||||
minutes = tz < 0 ? -minutes : minutes;
|
||||
t = time + minutes * 60;
|
||||
tm = gmtime(&t);
|
||||
|
||||
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", tm);
|
||||
strcat(time_buf, tz_str);
|
||||
else {
|
||||
tz = atoi(tz_str);
|
||||
time_str = show_date(time, tz, blame_date_mode);
|
||||
time_len = strlen(time_str);
|
||||
memcpy(time_buf, time_str, time_len);
|
||||
memset(time_buf + time_len, ' ', blame_date_width - time_len);
|
||||
}
|
||||
return time_buf;
|
||||
}
|
||||
|
||||
@ -1551,24 +1576,8 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent)
|
||||
ent->s_lno + 1,
|
||||
ent->lno + 1,
|
||||
ent->num_lines);
|
||||
if (!(suspect->commit->object.flags & METAINFO_SHOWN)) {
|
||||
struct commit_info ci;
|
||||
suspect->commit->object.flags |= METAINFO_SHOWN;
|
||||
get_commit_info(suspect->commit, &ci, 1);
|
||||
printf("author %s\n", ci.author);
|
||||
printf("author-mail %s\n", ci.author_mail);
|
||||
printf("author-time %lu\n", ci.author_time);
|
||||
printf("author-tz %s\n", ci.author_tz);
|
||||
printf("committer %s\n", ci.committer);
|
||||
printf("committer-mail %s\n", ci.committer_mail);
|
||||
printf("committer-time %lu\n", ci.committer_time);
|
||||
printf("committer-tz %s\n", ci.committer_tz);
|
||||
write_filename_info(suspect->path);
|
||||
printf("summary %s\n", ci.summary);
|
||||
if (suspect->commit->object.flags & UNINTERESTING)
|
||||
printf("boundary\n");
|
||||
}
|
||||
else if (suspect->commit->object.flags & MORE_THAN_ONE_PATH)
|
||||
if (emit_one_suspect_detail(suspect) ||
|
||||
(suspect->commit->object.flags & MORE_THAN_ONE_PATH))
|
||||
write_filename_info(suspect->path);
|
||||
|
||||
cp = nth_line(sb, ent->lno);
|
||||
@ -1806,36 +1815,6 @@ static void sanity_check_refcnt(struct scoreboard *sb)
|
||||
baa = 1;
|
||||
}
|
||||
}
|
||||
for (ent = sb->ent; ent; ent = ent->next) {
|
||||
/* Mark the ones that haven't been checked */
|
||||
if (0 < ent->suspect->refcnt)
|
||||
ent->suspect->refcnt = -ent->suspect->refcnt;
|
||||
}
|
||||
for (ent = sb->ent; ent; ent = ent->next) {
|
||||
/*
|
||||
* ... then pick each and see if they have the the
|
||||
* correct refcnt.
|
||||
*/
|
||||
int found;
|
||||
struct blame_entry *e;
|
||||
struct origin *suspect = ent->suspect;
|
||||
|
||||
if (0 < suspect->refcnt)
|
||||
continue;
|
||||
suspect->refcnt = -suspect->refcnt; /* Unmark */
|
||||
for (found = 0, e = sb->ent; e; e = e->next) {
|
||||
if (e->suspect != suspect)
|
||||
continue;
|
||||
found++;
|
||||
}
|
||||
if (suspect->refcnt != found) {
|
||||
fprintf(stderr, "%s in %s has refcnt %d, not %d\n",
|
||||
ent->suspect->path,
|
||||
sha1_to_hex(ent->suspect->commit->object.sha1),
|
||||
ent->suspect->refcnt, found);
|
||||
baa = 2;
|
||||
}
|
||||
}
|
||||
if (baa) {
|
||||
int opt = 0160;
|
||||
find_alignment(sb, &opt);
|
||||
@ -1975,6 +1954,12 @@ static int git_blame_config(const char *var, const char *value, void *cb)
|
||||
blank_boundary = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "blame.date")) {
|
||||
if (!value)
|
||||
return config_error_nonbool(var);
|
||||
blame_date_mode = parse_date_format(value);
|
||||
return 0;
|
||||
}
|
||||
return git_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
@ -2239,6 +2224,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||
|
||||
git_config(git_blame_config, NULL);
|
||||
init_revisions(&revs, NULL);
|
||||
revs.date_mode = blame_date_mode;
|
||||
|
||||
save_commit_buffer = 0;
|
||||
dashdash_pos = 0;
|
||||
|
||||
@ -2263,8 +2250,39 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||
parse_done:
|
||||
argc = parse_options_end(&ctx);
|
||||
|
||||
if (cmd_is_annotate)
|
||||
if (revs_file && read_ancestry(revs_file))
|
||||
die("reading graft file %s failed: %s",
|
||||
revs_file, strerror(errno));
|
||||
|
||||
if (cmd_is_annotate) {
|
||||
output_option |= OUTPUT_ANNOTATE_COMPAT;
|
||||
blame_date_mode = DATE_ISO8601;
|
||||
} else {
|
||||
blame_date_mode = revs.date_mode;
|
||||
}
|
||||
|
||||
/* The maximum width used to show the dates */
|
||||
switch (blame_date_mode) {
|
||||
case DATE_RFC2822:
|
||||
blame_date_width = sizeof("Thu, 19 Oct 2006 16:00:04 -0700");
|
||||
break;
|
||||
case DATE_ISO8601:
|
||||
blame_date_width = sizeof("2006-10-19 16:00:04 -0700");
|
||||
break;
|
||||
case DATE_RAW:
|
||||
blame_date_width = sizeof("1161298804 -0700");
|
||||
break;
|
||||
case DATE_SHORT:
|
||||
blame_date_width = sizeof("2006-10-19");
|
||||
break;
|
||||
case DATE_RELATIVE:
|
||||
/* "normal" is used as the fallback for "relative" */
|
||||
case DATE_LOCAL:
|
||||
case DATE_NORMAL:
|
||||
blame_date_width = sizeof("Thu Oct 19 16:00:04 2006 -0700");
|
||||
break;
|
||||
}
|
||||
blame_date_width -= 1; /* strip the null */
|
||||
|
||||
if (DIFF_OPT_TST(&revs.diffopt, FIND_COPIES_HARDER))
|
||||
opt |= (PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE |
|
||||
@ -2404,10 +2422,6 @@ parse_done:
|
||||
sb.ent = ent;
|
||||
sb.path = path;
|
||||
|
||||
if (revs_file && read_ancestry(revs_file))
|
||||
die("reading graft file %s failed: %s",
|
||||
revs_file, strerror(errno));
|
||||
|
||||
read_mailmap(&mailmap, NULL);
|
||||
|
||||
if (!incremental)
|
||||
|
206
builtin-branch.c
206
builtin-branch.c
@ -32,18 +32,18 @@ static unsigned char head_sha1[20];
|
||||
|
||||
static int branch_use_color = -1;
|
||||
static char branch_colors[][COLOR_MAXLEN] = {
|
||||
"\033[m", /* reset */
|
||||
"", /* PLAIN (normal) */
|
||||
"\033[31m", /* REMOTE (red) */
|
||||
"", /* LOCAL (normal) */
|
||||
"\033[32m", /* CURRENT (green) */
|
||||
GIT_COLOR_RESET,
|
||||
GIT_COLOR_NORMAL, /* PLAIN */
|
||||
GIT_COLOR_RED, /* REMOTE */
|
||||
GIT_COLOR_NORMAL, /* LOCAL */
|
||||
GIT_COLOR_GREEN, /* CURRENT */
|
||||
};
|
||||
enum color_branch {
|
||||
COLOR_BRANCH_RESET = 0,
|
||||
COLOR_BRANCH_PLAIN = 1,
|
||||
COLOR_BRANCH_REMOTE = 2,
|
||||
COLOR_BRANCH_LOCAL = 3,
|
||||
COLOR_BRANCH_CURRENT = 4,
|
||||
BRANCH_COLOR_RESET = 0,
|
||||
BRANCH_COLOR_PLAIN = 1,
|
||||
BRANCH_COLOR_REMOTE = 2,
|
||||
BRANCH_COLOR_LOCAL = 3,
|
||||
BRANCH_COLOR_CURRENT = 4,
|
||||
};
|
||||
|
||||
static enum merge_filter {
|
||||
@ -56,15 +56,15 @@ static unsigned char merge_filter_ref[20];
|
||||
static int parse_branch_color_slot(const char *var, int ofs)
|
||||
{
|
||||
if (!strcasecmp(var+ofs, "plain"))
|
||||
return COLOR_BRANCH_PLAIN;
|
||||
return BRANCH_COLOR_PLAIN;
|
||||
if (!strcasecmp(var+ofs, "reset"))
|
||||
return COLOR_BRANCH_RESET;
|
||||
return BRANCH_COLOR_RESET;
|
||||
if (!strcasecmp(var+ofs, "remote"))
|
||||
return COLOR_BRANCH_REMOTE;
|
||||
return BRANCH_COLOR_REMOTE;
|
||||
if (!strcasecmp(var+ofs, "local"))
|
||||
return COLOR_BRANCH_LOCAL;
|
||||
return BRANCH_COLOR_LOCAL;
|
||||
if (!strcasecmp(var+ofs, "current"))
|
||||
return COLOR_BRANCH_CURRENT;
|
||||
return BRANCH_COLOR_CURRENT;
|
||||
die("bad config variable '%s'", var);
|
||||
}
|
||||
|
||||
@ -121,11 +121,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
|
||||
die("Couldn't look up commit object for HEAD");
|
||||
}
|
||||
for (i = 0; i < argc; i++, strbuf_release(&bname)) {
|
||||
int len = strlen(argv[i]);
|
||||
|
||||
if (interpret_nth_last_branch(argv[i], &bname) != len)
|
||||
strbuf_add(&bname, argv[i], len);
|
||||
|
||||
strbuf_branchname(&bname, argv[i]);
|
||||
if (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {
|
||||
error("Cannot delete the branch '%s' "
|
||||
"which you are currently on.", bname.buf);
|
||||
@ -171,7 +167,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
|
||||
ret = 1;
|
||||
} else {
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
printf("Deleted %sbranch %s (%s).\n", remote,
|
||||
printf("Deleted %sbranch %s (was %s).\n", remote,
|
||||
bname.buf,
|
||||
find_unique_abbrev(sha1, DEFAULT_ABBREV));
|
||||
strbuf_addf(&buf, "branch.%s", bname.buf);
|
||||
@ -188,7 +184,8 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
|
||||
|
||||
struct ref_item {
|
||||
char *name;
|
||||
unsigned int kind;
|
||||
char *dest;
|
||||
unsigned int kind, len;
|
||||
struct commit *commit;
|
||||
};
|
||||
|
||||
@ -200,22 +197,47 @@ struct ref_list {
|
||||
int kinds;
|
||||
};
|
||||
|
||||
static char *resolve_symref(const char *src, const char *prefix)
|
||||
{
|
||||
unsigned char sha1[20];
|
||||
int flag;
|
||||
const char *dst, *cp;
|
||||
|
||||
dst = resolve_ref(src, sha1, 0, &flag);
|
||||
if (!(dst && (flag & REF_ISSYMREF)))
|
||||
return NULL;
|
||||
if (prefix && (cp = skip_prefix(dst, prefix)))
|
||||
dst = cp;
|
||||
return xstrdup(dst);
|
||||
}
|
||||
|
||||
static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
|
||||
{
|
||||
struct ref_list *ref_list = (struct ref_list*)(cb_data);
|
||||
struct ref_item *newitem;
|
||||
struct commit *commit;
|
||||
int kind;
|
||||
int len;
|
||||
int kind, i;
|
||||
const char *prefix, *orig_refname = refname;
|
||||
|
||||
static struct {
|
||||
int kind;
|
||||
const char *prefix;
|
||||
int pfxlen;
|
||||
} ref_kind[] = {
|
||||
{ REF_LOCAL_BRANCH, "refs/heads/", 11 },
|
||||
{ REF_REMOTE_BRANCH, "refs/remotes/", 13 },
|
||||
};
|
||||
|
||||
/* Detect kind */
|
||||
if (!prefixcmp(refname, "refs/heads/")) {
|
||||
kind = REF_LOCAL_BRANCH;
|
||||
refname += 11;
|
||||
} else if (!prefixcmp(refname, "refs/remotes/")) {
|
||||
kind = REF_REMOTE_BRANCH;
|
||||
refname += 13;
|
||||
} else
|
||||
for (i = 0; i < ARRAY_SIZE(ref_kind); i++) {
|
||||
prefix = ref_kind[i].prefix;
|
||||
if (strncmp(refname, prefix, ref_kind[i].pfxlen))
|
||||
continue;
|
||||
kind = ref_kind[i].kind;
|
||||
refname += ref_kind[i].pfxlen;
|
||||
break;
|
||||
}
|
||||
if (ARRAY_SIZE(ref_kind) <= i)
|
||||
return 0;
|
||||
|
||||
commit = lookup_commit_reference_gently(sha1, 1);
|
||||
@ -246,9 +268,14 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
|
||||
newitem->name = xstrdup(refname);
|
||||
newitem->kind = kind;
|
||||
newitem->commit = commit;
|
||||
len = strlen(newitem->name);
|
||||
if (len > ref_list->maxwidth)
|
||||
ref_list->maxwidth = len;
|
||||
newitem->len = strlen(refname);
|
||||
newitem->dest = resolve_symref(orig_refname, prefix);
|
||||
/* adjust for "remotes/" */
|
||||
if (newitem->kind == REF_REMOTE_BRANCH &&
|
||||
ref_list->kinds != REF_REMOTE_BRANCH)
|
||||
newitem->len += 8;
|
||||
if (newitem->len > ref_list->maxwidth)
|
||||
ref_list->maxwidth = newitem->len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -257,8 +284,10 @@ static void free_ref_list(struct ref_list *ref_list)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ref_list->index; i++)
|
||||
for (i = 0; i < ref_list->index; i++) {
|
||||
free(ref_list->list[i].name);
|
||||
free(ref_list->list[i].dest);
|
||||
}
|
||||
free(ref_list->list);
|
||||
}
|
||||
|
||||
@ -272,19 +301,30 @@ static int ref_cmp(const void *r1, const void *r2)
|
||||
return strcmp(c1->name, c2->name);
|
||||
}
|
||||
|
||||
static void fill_tracking_info(struct strbuf *stat, const char *branch_name)
|
||||
static void fill_tracking_info(struct strbuf *stat, const char *branch_name,
|
||||
int show_upstream_ref)
|
||||
{
|
||||
int ours, theirs;
|
||||
struct branch *branch = branch_get(branch_name);
|
||||
|
||||
if (!stat_tracking_info(branch, &ours, &theirs) || (!ours && !theirs))
|
||||
if (!stat_tracking_info(branch, &ours, &theirs)) {
|
||||
if (branch && branch->merge && branch->merge[0]->dst &&
|
||||
show_upstream_ref)
|
||||
strbuf_addf(stat, "[%s] ",
|
||||
shorten_unambiguous_ref(branch->merge[0]->dst));
|
||||
return;
|
||||
}
|
||||
|
||||
strbuf_addch(stat, '[');
|
||||
if (show_upstream_ref)
|
||||
strbuf_addf(stat, "%s: ",
|
||||
shorten_unambiguous_ref(branch->merge[0]->dst));
|
||||
if (!ours)
|
||||
strbuf_addf(stat, "[behind %d] ", theirs);
|
||||
strbuf_addf(stat, "behind %d] ", theirs);
|
||||
else if (!theirs)
|
||||
strbuf_addf(stat, "[ahead %d] ", ours);
|
||||
strbuf_addf(stat, "ahead %d] ", ours);
|
||||
else
|
||||
strbuf_addf(stat, "[ahead %d, behind %d] ", ours, theirs);
|
||||
strbuf_addf(stat, "ahead %d, behind %d] ", ours, theirs);
|
||||
}
|
||||
|
||||
static int matches_merge_filter(struct commit *commit)
|
||||
@ -299,34 +339,46 @@ static int matches_merge_filter(struct commit *commit)
|
||||
}
|
||||
|
||||
static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
|
||||
int abbrev, int current)
|
||||
int abbrev, int current, char *prefix)
|
||||
{
|
||||
char c;
|
||||
int color;
|
||||
struct commit *commit = item->commit;
|
||||
struct strbuf out = STRBUF_INIT, name = STRBUF_INIT;
|
||||
|
||||
if (!matches_merge_filter(commit))
|
||||
return;
|
||||
|
||||
switch (item->kind) {
|
||||
case REF_LOCAL_BRANCH:
|
||||
color = COLOR_BRANCH_LOCAL;
|
||||
color = BRANCH_COLOR_LOCAL;
|
||||
break;
|
||||
case REF_REMOTE_BRANCH:
|
||||
color = COLOR_BRANCH_REMOTE;
|
||||
color = BRANCH_COLOR_REMOTE;
|
||||
break;
|
||||
default:
|
||||
color = COLOR_BRANCH_PLAIN;
|
||||
color = BRANCH_COLOR_PLAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
c = ' ';
|
||||
if (current) {
|
||||
c = '*';
|
||||
color = COLOR_BRANCH_CURRENT;
|
||||
color = BRANCH_COLOR_CURRENT;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
strbuf_addf(&name, "%s%s", prefix, item->name);
|
||||
if (verbose)
|
||||
strbuf_addf(&out, "%c %s%-*s%s", c, branch_get_color(color),
|
||||
maxwidth, name.buf,
|
||||
branch_get_color(BRANCH_COLOR_RESET));
|
||||
else
|
||||
strbuf_addf(&out, "%c %s%s%s", c, branch_get_color(color),
|
||||
name.buf, branch_get_color(BRANCH_COLOR_RESET));
|
||||
|
||||
if (item->dest)
|
||||
strbuf_addf(&out, " -> %s", item->dest);
|
||||
else if (verbose) {
|
||||
struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
|
||||
const char *sub = " **** invalid ref ****";
|
||||
|
||||
@ -338,30 +390,27 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
|
||||
}
|
||||
|
||||
if (item->kind == REF_LOCAL_BRANCH)
|
||||
fill_tracking_info(&stat, item->name);
|
||||
fill_tracking_info(&stat, item->name, verbose > 1);
|
||||
|
||||
printf("%c %s%-*s%s %s %s%s\n", c, branch_get_color(color),
|
||||
maxwidth, item->name,
|
||||
branch_get_color(COLOR_BRANCH_RESET),
|
||||
find_unique_abbrev(item->commit->object.sha1, abbrev),
|
||||
stat.buf, sub);
|
||||
strbuf_addf(&out, " %s %s%s",
|
||||
find_unique_abbrev(item->commit->object.sha1, abbrev),
|
||||
stat.buf, sub);
|
||||
strbuf_release(&stat);
|
||||
strbuf_release(&subject);
|
||||
} else {
|
||||
printf("%c %s%s%s\n", c, branch_get_color(color), item->name,
|
||||
branch_get_color(COLOR_BRANCH_RESET));
|
||||
}
|
||||
printf("%s\n", out.buf);
|
||||
strbuf_release(&name);
|
||||
strbuf_release(&out);
|
||||
}
|
||||
|
||||
static int calc_maxwidth(struct ref_list *refs)
|
||||
{
|
||||
int i, l, w = 0;
|
||||
int i, w = 0;
|
||||
for (i = 0; i < refs->index; i++) {
|
||||
if (!matches_merge_filter(refs->list[i].commit))
|
||||
continue;
|
||||
l = strlen(refs->list[i].name);
|
||||
if (l > w)
|
||||
w = l;
|
||||
if (refs->list[i].len > w)
|
||||
w = refs->list[i].len;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
@ -397,11 +446,13 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str
|
||||
is_descendant_of(head_commit, with_commit)) {
|
||||
struct ref_item item;
|
||||
item.name = xstrdup("(no branch)");
|
||||
item.len = strlen(item.name);
|
||||
item.kind = REF_LOCAL_BRANCH;
|
||||
item.dest = NULL;
|
||||
item.commit = head_commit;
|
||||
if (strlen(item.name) > ref_list.maxwidth)
|
||||
ref_list.maxwidth = strlen(item.name);
|
||||
print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1);
|
||||
if (item.len > ref_list.maxwidth)
|
||||
ref_list.maxwidth = item.len;
|
||||
print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1, "");
|
||||
free(item.name);
|
||||
}
|
||||
|
||||
@ -409,8 +460,11 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str
|
||||
int current = !detached &&
|
||||
(ref_list.list[i].kind == REF_LOCAL_BRANCH) &&
|
||||
!strcmp(ref_list.list[i].name, head);
|
||||
char *prefix = (kinds != REF_REMOTE_BRANCH &&
|
||||
ref_list.list[i].kind == REF_REMOTE_BRANCH)
|
||||
? "remotes/" : "";
|
||||
print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose,
|
||||
abbrev, current);
|
||||
abbrev, current, prefix);
|
||||
}
|
||||
|
||||
free_ref_list(&ref_list);
|
||||
@ -421,22 +475,27 @@ static void rename_branch(const char *oldname, const char *newname, int force)
|
||||
struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
|
||||
unsigned char sha1[20];
|
||||
struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
|
||||
int recovery = 0;
|
||||
|
||||
if (!oldname)
|
||||
die("cannot rename the current branch while not on any.");
|
||||
|
||||
strbuf_addf(&oldref, "refs/heads/%s", oldname);
|
||||
if (strbuf_check_branch_ref(&oldref, oldname)) {
|
||||
/*
|
||||
* Bad name --- this could be an attempt to rename a
|
||||
* ref that we used to allow to be created by accident.
|
||||
*/
|
||||
if (resolve_ref(oldref.buf, sha1, 1, NULL))
|
||||
recovery = 1;
|
||||
else
|
||||
die("Invalid branch name: '%s'", oldname);
|
||||
}
|
||||
|
||||
if (check_ref_format(oldref.buf))
|
||||
die("Invalid branch name: %s", oldref.buf);
|
||||
|
||||
strbuf_addf(&newref, "refs/heads/%s", newname);
|
||||
|
||||
if (check_ref_format(newref.buf))
|
||||
die("Invalid branch name: %s", newref.buf);
|
||||
if (strbuf_check_branch_ref(&newref, newname))
|
||||
die("Invalid branch name: '%s'", newname);
|
||||
|
||||
if (resolve_ref(newref.buf, sha1, 1, NULL) && !force)
|
||||
die("A branch named '%s' already exists.", newname);
|
||||
die("A branch named '%s' already exists.", newref.buf + 11);
|
||||
|
||||
strbuf_addf(&logmsg, "Branch: renamed %s to %s",
|
||||
oldref.buf, newref.buf);
|
||||
@ -445,6 +504,9 @@ static void rename_branch(const char *oldname, const char *newname, int force)
|
||||
die("Branch rename failed");
|
||||
strbuf_release(&logmsg);
|
||||
|
||||
if (recovery)
|
||||
warning("Renamed a misnamed branch '%s' away", oldref.buf + 11);
|
||||
|
||||
/* no need to pass logmsg here as HEAD didn't really move */
|
||||
if (!strcmp(oldname, head) && create_symref("HEAD", newref.buf, NULL))
|
||||
die("Branch renamed to %s, but HEAD is not updated!", newname);
|
||||
|
@ -5,9 +5,18 @@
|
||||
#include "cache.h"
|
||||
#include "refs.h"
|
||||
#include "builtin.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
if (argc == 3 && !strcmp(argv[1], "--branch")) {
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
if (strbuf_check_branch_ref(&sb, argv[2]))
|
||||
die("'%s' is not a valid branch name", argv[2]);
|
||||
printf("%s\n", sb.buf + 11);
|
||||
exit(0);
|
||||
}
|
||||
if (argc != 2)
|
||||
usage("git check-ref-format refname");
|
||||
return !!check_ref_format(argv[1]);
|
||||
|
@ -53,9 +53,6 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,
|
||||
int len;
|
||||
struct cache_entry *ce;
|
||||
|
||||
if (S_ISGITLINK(mode))
|
||||
return 0;
|
||||
|
||||
if (S_ISDIR(mode))
|
||||
return READ_TREE_RECURSIVE;
|
||||
|
||||
@ -295,6 +292,8 @@ static void show_local_changes(struct object *head)
|
||||
init_revisions(&rev, NULL);
|
||||
rev.abbrev = 0;
|
||||
rev.diffopt.output_format |= DIFF_FORMAT_NAME_STATUS;
|
||||
if (diff_setup_done(&rev.diffopt) < 0)
|
||||
die("diff_setup_done failed");
|
||||
add_pending_object(&rev, head, NULL);
|
||||
run_diff_index(&rev, 0);
|
||||
}
|
||||
@ -351,16 +350,11 @@ struct branch_info {
|
||||
static void setup_branch_path(struct branch_info *branch)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
int ret;
|
||||
|
||||
if ((ret = interpret_nth_last_branch(branch->name, &buf))
|
||||
&& ret == strlen(branch->name)) {
|
||||
strbuf_branchname(&buf, branch->name);
|
||||
if (strcmp(buf.buf, branch->name))
|
||||
branch->name = xstrdup(buf.buf);
|
||||
strbuf_splice(&buf, 0, 0, "refs/heads/", 11);
|
||||
} else {
|
||||
strbuf_addstr(&buf, "refs/heads/");
|
||||
strbuf_addstr(&buf, branch->name);
|
||||
}
|
||||
strbuf_splice(&buf, 0, 0, "refs/heads/", 11);
|
||||
branch->path = strbuf_detach(&buf, NULL);
|
||||
}
|
||||
|
||||
@ -405,7 +399,7 @@ static int merge_working_tree(struct checkout_opts *opts,
|
||||
topts.verbose_update = !opts->quiet;
|
||||
topts.fn = twoway_merge;
|
||||
topts.dir = xcalloc(1, sizeof(*topts.dir));
|
||||
topts.dir->show_ignored = 1;
|
||||
topts.dir->flags |= DIR_SHOW_IGNORED;
|
||||
topts.dir->exclude_per_dir = ".gitignore";
|
||||
tree = parse_tree_indirect(old->commit->object.sha1);
|
||||
init_tree_desc(&trees[0], tree->buffer, tree->size);
|
||||
@ -501,10 +495,10 @@ static void update_refs_for_switch(struct checkout_opts *opts,
|
||||
create_symref("HEAD", new->path, msg.buf);
|
||||
if (!opts->quiet) {
|
||||
if (old->path && !strcmp(new->path, old->path))
|
||||
fprintf(stderr, "Already on \"%s\"\n",
|
||||
fprintf(stderr, "Already on '%s'\n",
|
||||
new->name);
|
||||
else
|
||||
fprintf(stderr, "Switched to%s branch \"%s\"\n",
|
||||
fprintf(stderr, "Switched to%s branch '%s'\n",
|
||||
opts->new_branch ? " a new" : "",
|
||||
new->name);
|
||||
}
|
||||
@ -513,7 +507,7 @@ static void update_refs_for_switch(struct checkout_opts *opts,
|
||||
REF_NODEREF, DIE_ON_ERR);
|
||||
if (!opts->quiet) {
|
||||
if (old->path)
|
||||
fprintf(stderr, "Note: moving to \"%s\" which isn't a local branch\nIf you want to create a new branch from this checkout, you may do so\n(now or later) by using -b with the checkout command again. Example:\n git checkout -b <new_branch_name>\n", new->name);
|
||||
fprintf(stderr, "Note: moving to '%s' which isn't a local branch\nIf you want to create a new branch from this checkout, you may do so\n(now or later) by using -b with the checkout command again. Example:\n git checkout -b <new_branch_name>\n", new->name);
|
||||
describe_detached_head("HEAD is now at", new->commit);
|
||||
}
|
||||
}
|
||||
@ -556,8 +550,8 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
|
||||
|
||||
if (!old.commit && !opts->force) {
|
||||
if (!opts->quiet) {
|
||||
fprintf(stderr, "warning: You appear to be on a branch yet to be born.\n");
|
||||
fprintf(stderr, "warning: Forcing checkout of %s.\n", new->name);
|
||||
warning("You appear to be on a branch yet to be born.");
|
||||
warning("Forcing checkout of %s.", new->name);
|
||||
}
|
||||
opts->force = 1;
|
||||
}
|
||||
@ -736,12 +730,11 @@ no_reference:
|
||||
|
||||
if (opts.new_branch) {
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
strbuf_addstr(&buf, "refs/heads/");
|
||||
strbuf_addstr(&buf, opts.new_branch);
|
||||
if (strbuf_check_branch_ref(&buf, opts.new_branch))
|
||||
die("git checkout: we do not like '%s' as a branch name.",
|
||||
opts.new_branch);
|
||||
if (!get_sha1(buf.buf, rev))
|
||||
die("git checkout: branch %s already exists", opts.new_branch);
|
||||
if (check_ref_format(buf.buf))
|
||||
die("git checkout: we do not like '%s' as a branch name.", opts.new_branch);
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
|
||||
memset(&dir, 0, sizeof(dir));
|
||||
if (ignored_only)
|
||||
dir.show_ignored = 1;
|
||||
dir.flags |= DIR_SHOW_IGNORED;
|
||||
|
||||
if (ignored && ignored_only)
|
||||
die("-x and -X cannot be used together");
|
||||
@ -69,7 +69,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
die("clean.requireForce%s set and -n or -f not given; "
|
||||
"refusing to clean", config_set ? "" : " not");
|
||||
|
||||
dir.show_other_directories = 1;
|
||||
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
|
||||
|
||||
if (!ignored)
|
||||
setup_standard_excludes(&dir);
|
||||
|
101
builtin-clone.c
101
builtin-clone.c
@ -20,6 +20,9 @@
|
||||
#include "dir.h"
|
||||
#include "pack-refs.h"
|
||||
#include "sigchain.h"
|
||||
#include "branch.h"
|
||||
#include "remote.h"
|
||||
#include "run-command.h"
|
||||
|
||||
/*
|
||||
* Overall FIXMEs:
|
||||
@ -267,7 +270,7 @@ static const struct ref *clone_local(const char *src_repo,
|
||||
|
||||
static const char *junk_work_tree;
|
||||
static const char *junk_git_dir;
|
||||
pid_t junk_pid;
|
||||
static pid_t junk_pid;
|
||||
|
||||
static void remove_junk(void)
|
||||
{
|
||||
@ -293,43 +296,6 @@ static void remove_junk_on_signal(int signo)
|
||||
raise(signo);
|
||||
}
|
||||
|
||||
static const struct ref *locate_head(const struct ref *refs,
|
||||
const struct ref *mapped_refs,
|
||||
const struct ref **remote_head_p)
|
||||
{
|
||||
const struct ref *remote_head = NULL;
|
||||
const struct ref *remote_master = NULL;
|
||||
const struct ref *r;
|
||||
for (r = refs; r; r = r->next)
|
||||
if (!strcmp(r->name, "HEAD"))
|
||||
remote_head = r;
|
||||
|
||||
for (r = mapped_refs; r; r = r->next)
|
||||
if (!strcmp(r->name, "refs/heads/master"))
|
||||
remote_master = r;
|
||||
|
||||
if (remote_head_p)
|
||||
*remote_head_p = remote_head;
|
||||
|
||||
/* If there's no HEAD value at all, never mind. */
|
||||
if (!remote_head)
|
||||
return NULL;
|
||||
|
||||
/* If refs/heads/master could be right, it is. */
|
||||
if (remote_master && !hashcmp(remote_master->old_sha1,
|
||||
remote_head->old_sha1))
|
||||
return remote_master;
|
||||
|
||||
/* Look for another ref that points there */
|
||||
for (r = mapped_refs; r; r = r->next)
|
||||
if (r != remote_head &&
|
||||
!hashcmp(r->old_sha1, remote_head->old_sha1))
|
||||
return r;
|
||||
|
||||
/* Nothing is the same */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ref *write_remote_refs(const struct ref *refs,
|
||||
struct refspec *refspec, const char *reflog)
|
||||
{
|
||||
@ -350,23 +316,8 @@ static struct ref *write_remote_refs(const struct ref *refs,
|
||||
return local_refs;
|
||||
}
|
||||
|
||||
static void install_branch_config(const char *local,
|
||||
const char *origin,
|
||||
const char *remote)
|
||||
{
|
||||
struct strbuf key = STRBUF_INIT;
|
||||
strbuf_addf(&key, "branch.%s.remote", local);
|
||||
git_config_set(key.buf, origin);
|
||||
strbuf_reset(&key);
|
||||
strbuf_addf(&key, "branch.%s.merge", local);
|
||||
git_config_set(key.buf, remote);
|
||||
strbuf_release(&key);
|
||||
}
|
||||
|
||||
int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int use_local_hardlinks = 1;
|
||||
int use_separate_remote = 1;
|
||||
int is_bundle = 0;
|
||||
struct stat buf;
|
||||
const char *repo_name, *repo, *work_tree, *git_dir;
|
||||
@ -377,8 +328,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
|
||||
struct transport *transport = NULL;
|
||||
char *src_ref_prefix = "refs/heads/";
|
||||
int err = 0;
|
||||
|
||||
struct refspec refspec;
|
||||
struct refspec *refspec;
|
||||
const char *fetch_pattern;
|
||||
|
||||
junk_pid = getpid();
|
||||
|
||||
@ -388,9 +341,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
if (argc == 0)
|
||||
die("You must specify a repository to clone.");
|
||||
|
||||
if (option_no_hardlinks)
|
||||
use_local_hardlinks = 0;
|
||||
|
||||
if (option_mirror)
|
||||
option_bare = 1;
|
||||
|
||||
@ -399,7 +349,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
die("--bare and --origin %s options are incompatible.",
|
||||
option_origin);
|
||||
option_no_checkout = 1;
|
||||
use_separate_remote = 0;
|
||||
}
|
||||
|
||||
if (!option_origin)
|
||||
@ -457,7 +406,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
atexit(remove_junk);
|
||||
sigchain_push_common(remove_junk_on_signal);
|
||||
|
||||
setenv(CONFIG_ENVIRONMENT, xstrdup(mkpath("%s/config", git_dir)), 1);
|
||||
setenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1);
|
||||
|
||||
if (safe_create_leading_directories_const(git_dir) < 0)
|
||||
die("could not create leading directories of '%s'", git_dir);
|
||||
@ -487,8 +436,14 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
strbuf_addf(&branch_top, "refs/remotes/%s/", option_origin);
|
||||
}
|
||||
|
||||
strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf);
|
||||
|
||||
if (option_mirror || !option_bare) {
|
||||
/* Configure the remote */
|
||||
strbuf_addf(&key, "remote.%s.fetch", option_origin);
|
||||
git_config_set_multivar(key.buf, value.buf, "^$", 0);
|
||||
strbuf_reset(&key);
|
||||
|
||||
if (option_mirror) {
|
||||
strbuf_addf(&key, "remote.%s.mirror", option_origin);
|
||||
git_config_set(key.buf, "true");
|
||||
@ -497,19 +452,13 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
|
||||
strbuf_addf(&key, "remote.%s.url", option_origin);
|
||||
git_config_set(key.buf, repo);
|
||||
strbuf_reset(&key);
|
||||
|
||||
strbuf_addf(&key, "remote.%s.fetch", option_origin);
|
||||
strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf);
|
||||
git_config_set_multivar(key.buf, value.buf, "^$", 0);
|
||||
strbuf_reset(&key);
|
||||
strbuf_reset(&value);
|
||||
}
|
||||
|
||||
refspec.force = 0;
|
||||
refspec.pattern = 1;
|
||||
refspec.src = src_ref_prefix;
|
||||
refspec.dst = branch_top.buf;
|
||||
fetch_pattern = value.buf;
|
||||
refspec = parse_fetch_refspec(1, &fetch_pattern);
|
||||
|
||||
strbuf_reset(&value);
|
||||
|
||||
if (path && !is_bundle)
|
||||
refs = clone_local(path, git_dir);
|
||||
@ -543,9 +492,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
if (refs) {
|
||||
clear_extra_refs();
|
||||
|
||||
mapped_refs = write_remote_refs(refs, &refspec, reflog_msg.buf);
|
||||
mapped_refs = write_remote_refs(refs, refspec, reflog_msg.buf);
|
||||
|
||||
head_points_at = locate_head(refs, mapped_refs, &remote_head);
|
||||
remote_head = find_ref_by_name(refs, "HEAD");
|
||||
head_points_at = guess_remote_head(remote_head, mapped_refs, 0);
|
||||
}
|
||||
else {
|
||||
warning("You appear to have cloned an empty repository.");
|
||||
@ -553,7 +503,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
remote_head = NULL;
|
||||
option_no_checkout = 1;
|
||||
if (!option_bare)
|
||||
install_branch_config("master", option_origin,
|
||||
install_branch_config(0, "master", option_origin,
|
||||
"refs/heads/master");
|
||||
}
|
||||
|
||||
@ -583,7 +533,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
head_points_at->peer_ref->name,
|
||||
reflog_msg.buf);
|
||||
|
||||
install_branch_config(head, option_origin,
|
||||
install_branch_config(0, head, option_origin,
|
||||
head_points_at->name);
|
||||
}
|
||||
} else if (remote_head) {
|
||||
@ -631,6 +581,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
if (write_cache(fd, active_cache, active_nr) ||
|
||||
commit_locked_index(lock_file))
|
||||
die("unable to write new index file");
|
||||
|
||||
err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1),
|
||||
sha1_to_hex(remote_head->old_sha1), "1", NULL);
|
||||
}
|
||||
|
||||
strbuf_release(&reflog_msg);
|
||||
@ -638,5 +591,5 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
strbuf_release(&key);
|
||||
strbuf_release(&value);
|
||||
junk_pid = 0;
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
@ -224,7 +224,8 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
|
||||
const char **pathspec = NULL;
|
||||
|
||||
if (interactive) {
|
||||
interactive_add(argc, argv, prefix);
|
||||
if (interactive_add(argc, argv, prefix) != 0)
|
||||
die("interactive add failed");
|
||||
if (read_cache_preload(NULL) < 0)
|
||||
die("index file corrupt");
|
||||
commit_style = COMMIT_AS_IS;
|
||||
|
425
builtin-config.c
425
builtin-config.c
@ -1,9 +1,12 @@
|
||||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "color.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static const char git_config_set_usage[] =
|
||||
"git config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]";
|
||||
static const char *const builtin_config_usage[] = {
|
||||
"git config [options]",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *key;
|
||||
static regex_t *key_regexp;
|
||||
@ -16,7 +19,67 @@ static int seen;
|
||||
static char delim = '=';
|
||||
static char key_delim = ' ';
|
||||
static char term = '\n';
|
||||
static enum { T_RAW, T_INT, T_BOOL, T_BOOL_OR_INT } type = T_RAW;
|
||||
|
||||
static int use_global_config, use_system_config;
|
||||
static const char *given_config_file;
|
||||
static int actions, types;
|
||||
static const char *get_color_slot, *get_colorbool_slot;
|
||||
static int end_null;
|
||||
|
||||
#define ACTION_GET (1<<0)
|
||||
#define ACTION_GET_ALL (1<<1)
|
||||
#define ACTION_GET_REGEXP (1<<2)
|
||||
#define ACTION_REPLACE_ALL (1<<3)
|
||||
#define ACTION_ADD (1<<4)
|
||||
#define ACTION_UNSET (1<<5)
|
||||
#define ACTION_UNSET_ALL (1<<6)
|
||||
#define ACTION_RENAME_SECTION (1<<7)
|
||||
#define ACTION_REMOVE_SECTION (1<<8)
|
||||
#define ACTION_LIST (1<<9)
|
||||
#define ACTION_EDIT (1<<10)
|
||||
#define ACTION_SET (1<<11)
|
||||
#define ACTION_SET_ALL (1<<12)
|
||||
#define ACTION_GET_COLOR (1<<13)
|
||||
#define ACTION_GET_COLORBOOL (1<<14)
|
||||
|
||||
#define TYPE_BOOL (1<<0)
|
||||
#define TYPE_INT (1<<1)
|
||||
#define TYPE_BOOL_OR_INT (1<<2)
|
||||
|
||||
static struct option builtin_config_options[] = {
|
||||
OPT_GROUP("Config file location"),
|
||||
OPT_BOOLEAN(0, "global", &use_global_config, "use global config file"),
|
||||
OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
|
||||
OPT_STRING('f', "file", &given_config_file, "FILE", "use given config file"),
|
||||
OPT_GROUP("Action"),
|
||||
OPT_BIT(0, "get", &actions, "get value: name [value-regex]", ACTION_GET),
|
||||
OPT_BIT(0, "get-all", &actions, "get all values: key [value-regex]", ACTION_GET_ALL),
|
||||
OPT_BIT(0, "get-regexp", &actions, "get values for regexp: name-regex [value-regex]", ACTION_GET_REGEXP),
|
||||
OPT_BIT(0, "replace-all", &actions, "replace all matching variables: name value [value_regex]", ACTION_REPLACE_ALL),
|
||||
OPT_BIT(0, "add", &actions, "adds a new variable: name value", ACTION_ADD),
|
||||
OPT_BIT(0, "unset", &actions, "removes a variable: name [value-regex]", ACTION_UNSET),
|
||||
OPT_BIT(0, "unset-all", &actions, "removes all matches: name [value-regex]", ACTION_UNSET_ALL),
|
||||
OPT_BIT(0, "rename-section", &actions, "rename section: old-name new-name", ACTION_RENAME_SECTION),
|
||||
OPT_BIT(0, "remove-section", &actions, "remove a section: name", ACTION_REMOVE_SECTION),
|
||||
OPT_BIT('l', "list", &actions, "list all", ACTION_LIST),
|
||||
OPT_BIT('e', "edit", &actions, "opens an editor", ACTION_EDIT),
|
||||
OPT_STRING(0, "get-color", &get_color_slot, "slot", "find the color configured: [default]"),
|
||||
OPT_STRING(0, "get-colorbool", &get_colorbool_slot, "slot", "find the color setting: [stdout-is-tty]"),
|
||||
OPT_GROUP("Type"),
|
||||
OPT_BIT(0, "bool", &types, "value is \"true\" or \"false\"", TYPE_BOOL),
|
||||
OPT_BIT(0, "int", &types, "value is decimal number", TYPE_INT),
|
||||
OPT_BIT(0, "bool-or-int", &types, "value is --bool or --int", TYPE_BOOL_OR_INT),
|
||||
OPT_GROUP("Other"),
|
||||
OPT_BOOLEAN('z', "null", &end_null, "terminate values with NUL byte"),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
static void check_argc(int argc, int min, int max) {
|
||||
if (argc >= min && argc <= max)
|
||||
return;
|
||||
error("wrong number of arguments");
|
||||
usage_with_options(builtin_config_usage, builtin_config_options);
|
||||
}
|
||||
|
||||
static int show_all_config(const char *key_, const char *value_, void *cb)
|
||||
{
|
||||
@ -27,7 +90,7 @@ static int show_all_config(const char *key_, const char *value_, void *cb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_config(const char* key_, const char* value_, void *cb)
|
||||
static int show_config(const char *key_, const char *value_, void *cb)
|
||||
{
|
||||
char value[256];
|
||||
const char *vptr = value;
|
||||
@ -49,11 +112,11 @@ static int show_config(const char* key_, const char* value_, void *cb)
|
||||
}
|
||||
if (seen && !do_all)
|
||||
dup_error = 1;
|
||||
if (type == T_INT)
|
||||
if (types == TYPE_INT)
|
||||
sprintf(value, "%d", git_config_int(key_, value_?value_:""));
|
||||
else if (type == T_BOOL)
|
||||
else if (types == TYPE_BOOL)
|
||||
vptr = git_config_bool(key_, value_) ? "true" : "false";
|
||||
else if (type == T_BOOL_OR_INT) {
|
||||
else if (types == TYPE_BOOL_OR_INT) {
|
||||
int is_bool, v;
|
||||
v = git_config_bool_or_int(key_, value_, &is_bool);
|
||||
if (is_bool)
|
||||
@ -74,7 +137,7 @@ static int show_config(const char* key_, const char* value_, void *cb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_value(const char* key_, const char* regex_)
|
||||
static int get_value(const char *key_, const char *regex_)
|
||||
{
|
||||
int ret = -1;
|
||||
char *tl;
|
||||
@ -152,18 +215,18 @@ static char *normalize_value(const char *key, const char *value)
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
if (type == T_RAW)
|
||||
if (types == 0)
|
||||
normalized = xstrdup(value);
|
||||
else {
|
||||
normalized = xmalloc(64);
|
||||
if (type == T_INT) {
|
||||
if (types == TYPE_INT) {
|
||||
int v = git_config_int(key, value);
|
||||
sprintf(normalized, "%d", v);
|
||||
}
|
||||
else if (type == T_BOOL)
|
||||
else if (types == TYPE_BOOL)
|
||||
sprintf(normalized, "%s",
|
||||
git_config_bool(key, value) ? "true" : "false");
|
||||
else if (type == T_BOOL_OR_INT) {
|
||||
else if (types == TYPE_BOOL_OR_INT) {
|
||||
int is_bool, v;
|
||||
v = git_config_bool_or_int(key, value, &is_bool);
|
||||
if (!is_bool)
|
||||
@ -178,6 +241,7 @@ static char *normalize_value(const char *key, const char *value)
|
||||
|
||||
static int get_color_found;
|
||||
static const char *get_color_slot;
|
||||
static const char *get_colorbool_slot;
|
||||
static char parsed_color[COLOR_MAXLEN];
|
||||
|
||||
static int git_get_color_config(const char *var, const char *value, void *cb)
|
||||
@ -191,29 +255,8 @@ static int git_get_color_config(const char *var, const char *value, void *cb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_color(int argc, const char **argv)
|
||||
static void get_color(const char *def_color)
|
||||
{
|
||||
/*
|
||||
* grab the color setting for the given slot from the configuration,
|
||||
* or parse the default value if missing, and return ANSI color
|
||||
* escape sequence.
|
||||
*
|
||||
* e.g.
|
||||
* git config --get-color color.diff.whitespace "blue reverse"
|
||||
*/
|
||||
const char *def_color = NULL;
|
||||
|
||||
switch (argc) {
|
||||
default:
|
||||
usage(git_config_set_usage);
|
||||
case 2:
|
||||
def_color = argv[1];
|
||||
/* fallthru */
|
||||
case 1:
|
||||
get_color_slot = argv[0];
|
||||
break;
|
||||
}
|
||||
|
||||
get_color_found = 0;
|
||||
parsed_color[0] = '\0';
|
||||
git_config(git_get_color_config, NULL);
|
||||
@ -222,7 +265,6 @@ static int get_color(int argc, const char **argv)
|
||||
color_parse(def_color, "command line", parsed_color);
|
||||
|
||||
fputs(parsed_color, stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stdout_is_tty;
|
||||
@ -231,7 +273,7 @@ static int get_diff_color_found;
|
||||
static int git_get_colorbool_config(const char *var, const char *value,
|
||||
void *cb)
|
||||
{
|
||||
if (!strcmp(var, get_color_slot)) {
|
||||
if (!strcmp(var, get_colorbool_slot)) {
|
||||
get_colorbool_found =
|
||||
git_config_colorbool(var, value, stdout_is_tty);
|
||||
}
|
||||
@ -246,183 +288,188 @@ static int git_get_colorbool_config(const char *var, const char *value,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_colorbool(int argc, const char **argv)
|
||||
static int get_colorbool(int print)
|
||||
{
|
||||
/*
|
||||
* git config --get-colorbool <slot> [<stdout-is-tty>]
|
||||
*
|
||||
* returns "true" or "false" depending on how <slot>
|
||||
* is configured.
|
||||
*/
|
||||
|
||||
if (argc == 2)
|
||||
stdout_is_tty = git_config_bool("command line", argv[1]);
|
||||
else if (argc == 1)
|
||||
stdout_is_tty = isatty(1);
|
||||
else
|
||||
usage(git_config_set_usage);
|
||||
get_colorbool_found = -1;
|
||||
get_diff_color_found = -1;
|
||||
get_color_slot = argv[0];
|
||||
git_config(git_get_colorbool_config, NULL);
|
||||
|
||||
if (get_colorbool_found < 0) {
|
||||
if (!strcmp(get_color_slot, "color.diff"))
|
||||
if (!strcmp(get_colorbool_slot, "color.diff"))
|
||||
get_colorbool_found = get_diff_color_found;
|
||||
if (get_colorbool_found < 0)
|
||||
get_colorbool_found = git_use_color_default;
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
return get_colorbool_found ? 0 : 1;
|
||||
} else {
|
||||
if (print) {
|
||||
printf("%s\n", get_colorbool_found ? "true" : "false");
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
return get_colorbool_found ? 0 : 1;
|
||||
}
|
||||
|
||||
int cmd_config(int argc, const char **argv, const char *prefix)
|
||||
int cmd_config(int argc, const char **argv, const char *unused_prefix)
|
||||
{
|
||||
int nongit;
|
||||
char* value;
|
||||
const char *file = setup_git_directory_gently(&nongit);
|
||||
char *value;
|
||||
const char *prefix = setup_git_directory_gently(&nongit);
|
||||
|
||||
config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
|
||||
|
||||
while (1 < argc) {
|
||||
if (!strcmp(argv[1], "--int"))
|
||||
type = T_INT;
|
||||
else if (!strcmp(argv[1], "--bool"))
|
||||
type = T_BOOL;
|
||||
else if (!strcmp(argv[1], "--bool-or-int"))
|
||||
type = T_BOOL_OR_INT;
|
||||
else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l")) {
|
||||
if (argc != 2)
|
||||
usage(git_config_set_usage);
|
||||
if (git_config(show_all_config, NULL) < 0 &&
|
||||
file && errno)
|
||||
die("unable to read config file %s: %s", file,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
else if (!strcmp(argv[1], "--global")) {
|
||||
char *home = getenv("HOME");
|
||||
if (home) {
|
||||
char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
|
||||
config_exclusive_filename = user_config;
|
||||
} else {
|
||||
die("$HOME not set");
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[1], "--system"))
|
||||
config_exclusive_filename = git_etc_gitconfig();
|
||||
else if (!strcmp(argv[1], "--file") || !strcmp(argv[1], "-f")) {
|
||||
if (argc < 3)
|
||||
usage(git_config_set_usage);
|
||||
if (!is_absolute_path(argv[2]) && file)
|
||||
file = prefix_filename(file, strlen(file),
|
||||
argv[2]);
|
||||
else
|
||||
file = argv[2];
|
||||
config_exclusive_filename = file;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
else if (!strcmp(argv[1], "--null") || !strcmp(argv[1], "-z")) {
|
||||
term = '\0';
|
||||
delim = '\n';
|
||||
key_delim = '\n';
|
||||
}
|
||||
else if (!strcmp(argv[1], "--rename-section")) {
|
||||
int ret;
|
||||
if (argc != 4)
|
||||
usage(git_config_set_usage);
|
||||
ret = git_config_rename_section(argv[2], argv[3]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 0) {
|
||||
fprintf(stderr, "No such section!\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (!strcmp(argv[1], "--remove-section")) {
|
||||
int ret;
|
||||
if (argc != 3)
|
||||
usage(git_config_set_usage);
|
||||
ret = git_config_rename_section(argv[2], NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 0) {
|
||||
fprintf(stderr, "No such section!\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} else if (!strcmp(argv[1], "--get-color")) {
|
||||
return get_color(argc-2, argv+2);
|
||||
} else if (!strcmp(argv[1], "--get-colorbool")) {
|
||||
return get_colorbool(argc-2, argv+2);
|
||||
} else
|
||||
break;
|
||||
argc--;
|
||||
argv++;
|
||||
argc = parse_options(argc, argv, builtin_config_options, builtin_config_usage,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
|
||||
if (use_global_config + use_system_config + !!given_config_file > 1) {
|
||||
error("only one config file at a time.");
|
||||
usage_with_options(builtin_config_usage, builtin_config_options);
|
||||
}
|
||||
|
||||
switch (argc) {
|
||||
case 2:
|
||||
return get_value(argv[1], NULL);
|
||||
case 3:
|
||||
if (!strcmp(argv[1], "--unset"))
|
||||
return git_config_set(argv[2], NULL);
|
||||
else if (!strcmp(argv[1], "--unset-all"))
|
||||
return git_config_set_multivar(argv[2], NULL, NULL, 1);
|
||||
else if (!strcmp(argv[1], "--get"))
|
||||
return get_value(argv[2], NULL);
|
||||
else if (!strcmp(argv[1], "--get-all")) {
|
||||
do_all = 1;
|
||||
return get_value(argv[2], NULL);
|
||||
} else if (!strcmp(argv[1], "--get-regexp")) {
|
||||
show_keys = 1;
|
||||
use_key_regexp = 1;
|
||||
do_all = 1;
|
||||
return get_value(argv[2], NULL);
|
||||
if (use_global_config) {
|
||||
char *home = getenv("HOME");
|
||||
if (home) {
|
||||
char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
|
||||
config_exclusive_filename = user_config;
|
||||
} else {
|
||||
value = normalize_value(argv[1], argv[2]);
|
||||
return git_config_set(argv[1], value);
|
||||
die("$HOME not set");
|
||||
}
|
||||
case 4:
|
||||
if (!strcmp(argv[1], "--unset"))
|
||||
return git_config_set_multivar(argv[2], NULL, argv[3], 0);
|
||||
else if (!strcmp(argv[1], "--unset-all"))
|
||||
return git_config_set_multivar(argv[2], NULL, argv[3], 1);
|
||||
else if (!strcmp(argv[1], "--get"))
|
||||
return get_value(argv[2], argv[3]);
|
||||
else if (!strcmp(argv[1], "--get-all")) {
|
||||
do_all = 1;
|
||||
return get_value(argv[2], argv[3]);
|
||||
} else if (!strcmp(argv[1], "--get-regexp")) {
|
||||
show_keys = 1;
|
||||
use_key_regexp = 1;
|
||||
do_all = 1;
|
||||
return get_value(argv[2], argv[3]);
|
||||
} else if (!strcmp(argv[1], "--add")) {
|
||||
value = normalize_value(argv[2], argv[3]);
|
||||
return git_config_set_multivar(argv[2], value, "^$", 0);
|
||||
} else if (!strcmp(argv[1], "--replace-all")) {
|
||||
value = normalize_value(argv[2], argv[3]);
|
||||
return git_config_set_multivar(argv[2], value, NULL, 1);
|
||||
} else {
|
||||
value = normalize_value(argv[1], argv[2]);
|
||||
return git_config_set_multivar(argv[1], value, argv[3], 0);
|
||||
}
|
||||
case 5:
|
||||
if (!strcmp(argv[1], "--replace-all")) {
|
||||
value = normalize_value(argv[2], argv[3]);
|
||||
return git_config_set_multivar(argv[2], value, argv[4], 1);
|
||||
}
|
||||
case 1:
|
||||
default:
|
||||
usage(git_config_set_usage);
|
||||
}
|
||||
else if (use_system_config)
|
||||
config_exclusive_filename = git_etc_gitconfig();
|
||||
else if (given_config_file) {
|
||||
if (!is_absolute_path(given_config_file) && prefix)
|
||||
config_exclusive_filename = prefix_filename(prefix,
|
||||
strlen(prefix),
|
||||
argv[2]);
|
||||
else
|
||||
config_exclusive_filename = given_config_file;
|
||||
}
|
||||
|
||||
if (end_null) {
|
||||
term = '\0';
|
||||
delim = '\n';
|
||||
key_delim = '\n';
|
||||
}
|
||||
|
||||
if (HAS_MULTI_BITS(types)) {
|
||||
error("only one type at a time.");
|
||||
usage_with_options(builtin_config_usage, builtin_config_options);
|
||||
}
|
||||
|
||||
if (get_color_slot)
|
||||
actions |= ACTION_GET_COLOR;
|
||||
if (get_colorbool_slot)
|
||||
actions |= ACTION_GET_COLORBOOL;
|
||||
|
||||
if ((get_color_slot || get_colorbool_slot) && types) {
|
||||
error("--get-color and variable type are incoherent");
|
||||
usage_with_options(builtin_config_usage, builtin_config_options);
|
||||
}
|
||||
|
||||
if (HAS_MULTI_BITS(actions)) {
|
||||
error("only one action at a time.");
|
||||
usage_with_options(builtin_config_usage, builtin_config_options);
|
||||
}
|
||||
if (actions == 0)
|
||||
switch (argc) {
|
||||
case 1: actions = ACTION_GET; break;
|
||||
case 2: actions = ACTION_SET; break;
|
||||
case 3: actions = ACTION_SET_ALL; break;
|
||||
default:
|
||||
usage_with_options(builtin_config_usage, builtin_config_options);
|
||||
}
|
||||
|
||||
if (actions == ACTION_LIST) {
|
||||
check_argc(argc, 0, 0);
|
||||
if (git_config(show_all_config, NULL) < 0) {
|
||||
if (config_exclusive_filename)
|
||||
die("unable to read config file %s: %s",
|
||||
config_exclusive_filename, strerror(errno));
|
||||
else
|
||||
die("error processing config file(s)");
|
||||
}
|
||||
}
|
||||
else if (actions == ACTION_EDIT) {
|
||||
check_argc(argc, 0, 0);
|
||||
git_config(git_default_config, NULL);
|
||||
launch_editor(config_exclusive_filename ?
|
||||
config_exclusive_filename : git_path("config"),
|
||||
NULL, NULL);
|
||||
}
|
||||
else if (actions == ACTION_SET) {
|
||||
check_argc(argc, 2, 2);
|
||||
value = normalize_value(argv[0], argv[1]);
|
||||
return git_config_set(argv[0], value);
|
||||
}
|
||||
else if (actions == ACTION_SET_ALL) {
|
||||
check_argc(argc, 2, 3);
|
||||
value = normalize_value(argv[0], argv[1]);
|
||||
return git_config_set_multivar(argv[0], value, argv[2], 0);
|
||||
}
|
||||
else if (actions == ACTION_ADD) {
|
||||
check_argc(argc, 2, 2);
|
||||
value = normalize_value(argv[0], argv[1]);
|
||||
return git_config_set_multivar(argv[0], value, "^$", 0);
|
||||
}
|
||||
else if (actions == ACTION_REPLACE_ALL) {
|
||||
check_argc(argc, 2, 3);
|
||||
value = normalize_value(argv[0], argv[1]);
|
||||
return git_config_set_multivar(argv[0], value, argv[2], 1);
|
||||
}
|
||||
else if (actions == ACTION_GET) {
|
||||
check_argc(argc, 1, 2);
|
||||
return get_value(argv[0], argv[1]);
|
||||
}
|
||||
else if (actions == ACTION_GET_ALL) {
|
||||
do_all = 1;
|
||||
check_argc(argc, 1, 2);
|
||||
return get_value(argv[0], argv[1]);
|
||||
}
|
||||
else if (actions == ACTION_GET_REGEXP) {
|
||||
show_keys = 1;
|
||||
use_key_regexp = 1;
|
||||
do_all = 1;
|
||||
check_argc(argc, 1, 2);
|
||||
return get_value(argv[0], argv[1]);
|
||||
}
|
||||
else if (actions == ACTION_UNSET) {
|
||||
check_argc(argc, 1, 2);
|
||||
if (argc == 2)
|
||||
return git_config_set_multivar(argv[0], NULL, argv[1], 0);
|
||||
else
|
||||
return git_config_set(argv[0], NULL);
|
||||
}
|
||||
else if (actions == ACTION_UNSET_ALL) {
|
||||
check_argc(argc, 1, 2);
|
||||
return git_config_set_multivar(argv[0], NULL, argv[1], 1);
|
||||
}
|
||||
else if (actions == ACTION_RENAME_SECTION) {
|
||||
int ret;
|
||||
check_argc(argc, 2, 2);
|
||||
ret = git_config_rename_section(argv[0], argv[1]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 0)
|
||||
die("No such section!");
|
||||
}
|
||||
else if (actions == ACTION_REMOVE_SECTION) {
|
||||
int ret;
|
||||
check_argc(argc, 1, 1);
|
||||
ret = git_config_rename_section(argv[0], NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 0)
|
||||
die("No such section!");
|
||||
}
|
||||
else if (actions == ACTION_GET_COLOR) {
|
||||
get_color(argv[0]);
|
||||
}
|
||||
else if (actions == ACTION_GET_COLORBOOL) {
|
||||
if (argc == 1)
|
||||
stdout_is_tty = git_config_bool("command line", argv[0]);
|
||||
else if (argc == 0)
|
||||
stdout_is_tty = isatty(1);
|
||||
return get_colorbool(argc != 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
|
||||
hex[40] = 0;
|
||||
if (get_sha1_hex(hex, sha1))
|
||||
die("internal error");
|
||||
if (has_sha1_pack(sha1, NULL))
|
||||
if (has_sha1_pack(sha1))
|
||||
(*packed_loose)++;
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,6 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
|
||||
|
||||
init_revisions(opt, prefix);
|
||||
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
|
||||
nr_sha1 = 0;
|
||||
opt->abbrev = 0;
|
||||
opt->diff = 1;
|
||||
argc = setup_revisions(argc, argv, opt, NULL);
|
||||
|
@ -221,7 +221,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
|
||||
if (message)
|
||||
message += 2;
|
||||
|
||||
if (commit->parents) {
|
||||
if (commit->parents &&
|
||||
get_object_mark(&commit->parents->item->object) != 0) {
|
||||
parse_commit(commit->parents->item);
|
||||
diff_tree_sha1(commit->parents->item->tree->object.sha1,
|
||||
commit->tree->object.sha1, "", &rev->diffopt);
|
||||
@ -362,7 +363,10 @@ static void get_tags_and_duplicates(struct object_array *pending,
|
||||
break;
|
||||
case OBJ_TAG:
|
||||
tag = (struct tag *)e->item;
|
||||
|
||||
/* handle nested tags */
|
||||
while (tag && tag->object.type == OBJ_TAG) {
|
||||
parse_object(tag->object.sha1);
|
||||
string_list_append(full_name, extra_refs)->util = tag;
|
||||
tag = (struct tag *)tag->tagged;
|
||||
}
|
||||
@ -375,11 +379,17 @@ static void get_tags_and_duplicates(struct object_array *pending,
|
||||
case OBJ_BLOB:
|
||||
handle_object(tag->object.sha1);
|
||||
continue;
|
||||
default: /* OBJ_TAG (nested tags) is already handled */
|
||||
warning("Tag points to object of unexpected type %s, skipping.",
|
||||
typename(tag->object.type));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
die ("Unexpected object of type %s",
|
||||
typename(e->item->type));
|
||||
warning("%s: Unexpected object of type %s, skipping.",
|
||||
e->name,
|
||||
typename(e->item->type));
|
||||
continue;
|
||||
}
|
||||
if (commit->util)
|
||||
/* more than one name for the same object */
|
||||
|
@ -216,9 +216,8 @@ static int find_common(int fd[2], unsigned char *result_sha1,
|
||||
if (args.depth > 0) {
|
||||
char line[1024];
|
||||
unsigned char sha1[20];
|
||||
int len;
|
||||
|
||||
while ((len = packet_read_line(fd[0], line, sizeof(line)))) {
|
||||
while (packet_read_line(fd[0], line, sizeof(line))) {
|
||||
if (!prefixcmp(line, "shallow ")) {
|
||||
if (get_sha1_hex(line + 8, sha1))
|
||||
die("invalid shallow line: %s", line);
|
||||
@ -483,7 +482,7 @@ static int sideband_demux(int fd, void *data)
|
||||
{
|
||||
int *xd = data;
|
||||
|
||||
return recv_sideband("fetch-pack", xd[0], fd, 2);
|
||||
return recv_sideband("fetch-pack", xd[0], fd);
|
||||
}
|
||||
|
||||
static int get_pack(int xd[2], char **pack_lockfile)
|
||||
@ -606,7 +605,7 @@ static struct ref *do_fetch_pack(int fd[2],
|
||||
/* When cloning, it is not unusual to have
|
||||
* no common commit.
|
||||
*/
|
||||
fprintf(stderr, "warning: no common commits\n");
|
||||
warning("no common commits");
|
||||
|
||||
if (get_pack(fd, pack_lockfile))
|
||||
die("git fetch-pack: fetch failed.");
|
||||
@ -801,15 +800,13 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
|
||||
int fd;
|
||||
|
||||
mtime.sec = st.st_mtime;
|
||||
#ifdef USE_NSEC
|
||||
mtime.usec = st.st_mtim.usec;
|
||||
#endif
|
||||
mtime.nsec = ST_MTIME_NSEC(st);
|
||||
if (stat(shallow, &st)) {
|
||||
if (mtime.sec)
|
||||
die("shallow file was removed during fetch");
|
||||
} else if (st.st_mtime != mtime.sec
|
||||
#ifdef USE_NSEC
|
||||
|| st.st_mtim.usec != mtime.usec
|
||||
|| ST_MTIME_NSEC(st) != mtime.nsec
|
||||
#endif
|
||||
)
|
||||
die("shallow file was changed during fetch");
|
||||
|
@ -197,11 +197,7 @@ static int update_local_ref(struct ref *ref,
|
||||
struct commit *current = NULL, *updated;
|
||||
enum object_type type;
|
||||
struct branch *current_branch = branch_get(NULL);
|
||||
const char *pretty_ref = ref->name + (
|
||||
!prefixcmp(ref->name, "refs/heads/") ? 11 :
|
||||
!prefixcmp(ref->name, "refs/tags/") ? 10 :
|
||||
!prefixcmp(ref->name, "refs/remotes/") ? 13 :
|
||||
0);
|
||||
const char *pretty_ref = prettify_ref(ref);
|
||||
|
||||
*display = 0;
|
||||
type = sha1_object_info(ref->new_sha1, NULL);
|
||||
@ -544,7 +540,8 @@ static void check_not_current_branch(struct ref *ref_map)
|
||||
for (; ref_map; ref_map = ref_map->next)
|
||||
if (ref_map->peer_ref && !strcmp(current_branch->refname,
|
||||
ref_map->peer_ref->name))
|
||||
die("Refusing to fetch into current branch");
|
||||
die("Refusing to fetch into current branch %s "
|
||||
"of non-bare repository", current_branch->refname);
|
||||
}
|
||||
|
||||
static int do_fetch(struct transport *transport,
|
||||
|
@ -256,8 +256,7 @@ static void shortlog(const char *name, unsigned char *sha1,
|
||||
|
||||
int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) {
|
||||
int limit = 20, i = 0, pos = 0;
|
||||
char line[1024];
|
||||
char *p = line, *sep = "";
|
||||
char *sep = "";
|
||||
unsigned char head_sha1[20];
|
||||
const char *current_branch;
|
||||
|
||||
@ -271,9 +270,8 @@ int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) {
|
||||
/* get a line */
|
||||
while (pos < in->len) {
|
||||
int len;
|
||||
char *newline;
|
||||
char *newline, *p = in->buf + pos;
|
||||
|
||||
p = in->buf + pos;
|
||||
newline = strchr(p, '\n');
|
||||
len = newline ? newline - p : strlen(p);
|
||||
pos += len + !!newline;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "blob.h"
|
||||
#include "quote.h"
|
||||
#include "parse-options.h"
|
||||
#include "remote.h"
|
||||
|
||||
/* Quoting styles */
|
||||
#define QUOTE_NONE 0
|
||||
@ -66,6 +67,7 @@ static struct {
|
||||
{ "subject" },
|
||||
{ "body" },
|
||||
{ "contents" },
|
||||
{ "upstream" },
|
||||
};
|
||||
|
||||
/*
|
||||
@ -543,109 +545,6 @@ static void grab_values(struct atom_value *val, int deref, struct object *obj, v
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* generate a format suitable for scanf from a ref_rev_parse_rules
|
||||
* rule, that is replace the "%.*s" spec with a "%s" spec
|
||||
*/
|
||||
static void gen_scanf_fmt(char *scanf_fmt, const char *rule)
|
||||
{
|
||||
char *spec;
|
||||
|
||||
spec = strstr(rule, "%.*s");
|
||||
if (!spec || strstr(spec + 4, "%.*s"))
|
||||
die("invalid rule in ref_rev_parse_rules: %s", rule);
|
||||
|
||||
/* copy all until spec */
|
||||
strncpy(scanf_fmt, rule, spec - rule);
|
||||
scanf_fmt[spec - rule] = '\0';
|
||||
/* copy new spec */
|
||||
strcat(scanf_fmt, "%s");
|
||||
/* copy remaining rule */
|
||||
strcat(scanf_fmt, spec + 4);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shorten the refname to an non-ambiguous form
|
||||
*/
|
||||
static char *get_short_ref(struct refinfo *ref)
|
||||
{
|
||||
int i;
|
||||
static char **scanf_fmts;
|
||||
static int nr_rules;
|
||||
char *short_name;
|
||||
|
||||
/* pre generate scanf formats from ref_rev_parse_rules[] */
|
||||
if (!nr_rules) {
|
||||
size_t total_len = 0;
|
||||
|
||||
/* the rule list is NULL terminated, count them first */
|
||||
for (; ref_rev_parse_rules[nr_rules]; nr_rules++)
|
||||
/* no +1 because strlen("%s") < strlen("%.*s") */
|
||||
total_len += strlen(ref_rev_parse_rules[nr_rules]);
|
||||
|
||||
scanf_fmts = xmalloc(nr_rules * sizeof(char *) + total_len);
|
||||
|
||||
total_len = 0;
|
||||
for (i = 0; i < nr_rules; i++) {
|
||||
scanf_fmts[i] = (char *)&scanf_fmts[nr_rules]
|
||||
+ total_len;
|
||||
gen_scanf_fmt(scanf_fmts[i], ref_rev_parse_rules[i]);
|
||||
total_len += strlen(ref_rev_parse_rules[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* bail out if there are no rules */
|
||||
if (!nr_rules)
|
||||
return ref->refname;
|
||||
|
||||
/* buffer for scanf result, at most ref->refname must fit */
|
||||
short_name = xstrdup(ref->refname);
|
||||
|
||||
/* skip first rule, it will always match */
|
||||
for (i = nr_rules - 1; i > 0 ; --i) {
|
||||
int j;
|
||||
int short_name_len;
|
||||
|
||||
if (1 != sscanf(ref->refname, scanf_fmts[i], short_name))
|
||||
continue;
|
||||
|
||||
short_name_len = strlen(short_name);
|
||||
|
||||
/*
|
||||
* check if the short name resolves to a valid ref,
|
||||
* but use only rules prior to the matched one
|
||||
*/
|
||||
for (j = 0; j < i; j++) {
|
||||
const char *rule = ref_rev_parse_rules[j];
|
||||
unsigned char short_objectname[20];
|
||||
char refname[PATH_MAX];
|
||||
|
||||
/*
|
||||
* the short name is ambiguous, if it resolves
|
||||
* (with this previous rule) to a valid ref
|
||||
* read_ref() returns 0 on success
|
||||
*/
|
||||
mksnpath(refname, sizeof(refname),
|
||||
rule, short_name_len, short_name);
|
||||
if (!read_ref(refname, short_objectname))
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* short name is non-ambiguous if all previous rules
|
||||
* haven't resolved to a valid ref
|
||||
*/
|
||||
if (j == i)
|
||||
return short_name;
|
||||
}
|
||||
|
||||
free(short_name);
|
||||
return ref->refname;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse the object referred by ref, and grab needed value.
|
||||
*/
|
||||
@ -672,32 +571,49 @@ static void populate_value(struct refinfo *ref)
|
||||
const char *name = used_atom[i];
|
||||
struct atom_value *v = &ref->value[i];
|
||||
int deref = 0;
|
||||
const char *refname;
|
||||
const char *formatp;
|
||||
|
||||
if (*name == '*') {
|
||||
deref = 1;
|
||||
name++;
|
||||
}
|
||||
if (!prefixcmp(name, "refname")) {
|
||||
const char *formatp = strchr(name, ':');
|
||||
const char *refname = ref->refname;
|
||||
|
||||
/* look for "short" refname format */
|
||||
if (formatp) {
|
||||
formatp++;
|
||||
if (!strcmp(formatp, "short"))
|
||||
refname = get_short_ref(ref);
|
||||
else
|
||||
die("unknown refname format %s",
|
||||
formatp);
|
||||
}
|
||||
if (!prefixcmp(name, "refname"))
|
||||
refname = ref->refname;
|
||||
else if(!prefixcmp(name, "upstream")) {
|
||||
struct branch *branch;
|
||||
/* only local branches may have an upstream */
|
||||
if (prefixcmp(ref->refname, "refs/heads/"))
|
||||
continue;
|
||||
branch = branch_get(ref->refname + 11);
|
||||
|
||||
if (!deref)
|
||||
v->s = refname;
|
||||
else {
|
||||
int len = strlen(refname);
|
||||
char *s = xmalloc(len + 4);
|
||||
sprintf(s, "%s^{}", refname);
|
||||
v->s = s;
|
||||
}
|
||||
if (!branch || !branch->merge || !branch->merge[0] ||
|
||||
!branch->merge[0]->dst)
|
||||
continue;
|
||||
refname = branch->merge[0]->dst;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
formatp = strchr(name, ':');
|
||||
/* look for "short" refname format */
|
||||
if (formatp) {
|
||||
formatp++;
|
||||
if (!strcmp(formatp, "short"))
|
||||
refname = shorten_unambiguous_ref(refname);
|
||||
else
|
||||
die("unknown %.*s format %s",
|
||||
(int)(formatp - name), name, formatp);
|
||||
}
|
||||
|
||||
if (!deref)
|
||||
v->s = refname;
|
||||
else {
|
||||
int len = strlen(refname);
|
||||
char *s = xmalloc(len + 4);
|
||||
sprintf(s, "%s^{}", refname);
|
||||
v->s = s;
|
||||
}
|
||||
}
|
||||
|
||||
@ -943,7 +859,6 @@ static int opt_parse_sort(const struct option *opt, const char *arg, int unset)
|
||||
return -1;
|
||||
|
||||
*sort_tail = s = xcalloc(1, sizeof(*s));
|
||||
sort_tail = &s->next;
|
||||
|
||||
if (*arg == '-') {
|
||||
s->reverse = 1;
|
||||
|
@ -160,7 +160,7 @@ static void check_reachable_object(struct object *obj)
|
||||
* do a full fsck
|
||||
*/
|
||||
if (!obj->parsed) {
|
||||
if (has_sha1_pack(obj->sha1, NULL))
|
||||
if (has_sha1_pack(obj->sha1))
|
||||
return; /* it is in pack - forget about it */
|
||||
printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1));
|
||||
errors_found |= ERROR_REACHABLE;
|
||||
|
@ -23,7 +23,7 @@ static const char * const builtin_gc_usage[] = {
|
||||
};
|
||||
|
||||
static int pack_refs = 1;
|
||||
static int aggressive_window = -1;
|
||||
static int aggressive_window = 250;
|
||||
static int gc_auto_threshold = 6700;
|
||||
static int gc_auto_pack_limit = 50;
|
||||
static const char *prune_expire = "2.weeks.ago";
|
||||
@ -200,6 +200,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
|
||||
|
||||
if (aggressive) {
|
||||
append_option(argv_repack, "-f", MAX_ADD);
|
||||
append_option(argv_repack, "--depth=250", MAX_ADD);
|
||||
if (aggressive_window > 0) {
|
||||
sprintf(buf, "--window=%d", aggressive_window);
|
||||
append_option(argv_repack, buf, MAX_ADD);
|
||||
|
@ -22,6 +22,28 @@
|
||||
|
||||
static int builtin_grep;
|
||||
|
||||
static int grep_config(const char *var, const char *value, void *cb)
|
||||
{
|
||||
struct grep_opt *opt = cb;
|
||||
|
||||
if (!strcmp(var, "grep.color") || !strcmp(var, "color.grep")) {
|
||||
opt->color = git_config_colorbool(var, value, -1);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "grep.color.external") ||
|
||||
!strcmp(var, "color.grep.external")) {
|
||||
return git_config_string(&(opt->color_external), var, value);
|
||||
}
|
||||
if (!strcmp(var, "grep.color.match") ||
|
||||
!strcmp(var, "color.grep.match")) {
|
||||
if (!value)
|
||||
return config_error_nonbool(var);
|
||||
color_parse(value, var, opt->color_match);
|
||||
return 0;
|
||||
}
|
||||
return git_color_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
/*
|
||||
* git grep pathspecs are somewhat different from diff-tree pathspecs;
|
||||
* pathname wildcards are allowed.
|
||||
@ -269,6 +291,21 @@ static int flush_grep(struct grep_opt *opt,
|
||||
return status;
|
||||
}
|
||||
|
||||
static void grep_add_color(struct strbuf *sb, const char *escape_seq)
|
||||
{
|
||||
size_t orig_len = sb->len;
|
||||
|
||||
while (*escape_seq) {
|
||||
if (*escape_seq == 'm')
|
||||
strbuf_addch(sb, ';');
|
||||
else if (*escape_seq != '\033' && *escape_seq != '[')
|
||||
strbuf_addch(sb, *escape_seq);
|
||||
escape_seq++;
|
||||
}
|
||||
if (sb->len > orig_len && sb->buf[sb->len - 1] == ';')
|
||||
strbuf_setlen(sb, sb->len - 1);
|
||||
}
|
||||
|
||||
static int external_grep(struct grep_opt *opt, const char **paths, int cached)
|
||||
{
|
||||
int i, nr, argc, hit, len, status;
|
||||
@ -339,6 +376,23 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
|
||||
push_arg("-e");
|
||||
push_arg(p->pattern);
|
||||
}
|
||||
if (opt->color) {
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
grep_add_color(&sb, opt->color_match);
|
||||
setenv("GREP_COLOR", sb.buf, 1);
|
||||
|
||||
strbuf_reset(&sb);
|
||||
strbuf_addstr(&sb, "mt=");
|
||||
grep_add_color(&sb, opt->color_match);
|
||||
strbuf_addstr(&sb, ":sl=:cx=:fn=:ln=:bn=:se=");
|
||||
setenv("GREP_COLORS", sb.buf, 1);
|
||||
|
||||
strbuf_release(&sb);
|
||||
|
||||
if (opt->color_external && strlen(opt->color_external) > 0)
|
||||
push_arg(opt->color_external);
|
||||
}
|
||||
|
||||
hit = 0;
|
||||
argc = nr;
|
||||
@ -536,6 +590,12 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
opt.pattern_tail = &opt.pattern_list;
|
||||
opt.regflags = REG_NEWLINE;
|
||||
|
||||
strcpy(opt.color_match, GIT_COLOR_RED GIT_COLOR_BOLD);
|
||||
opt.color = -1;
|
||||
git_config(grep_config, &opt);
|
||||
if (opt.color == -1)
|
||||
opt.color = git_use_color_default;
|
||||
|
||||
/*
|
||||
* If there is no -- then the paths must exist in the working
|
||||
* tree. If there is no explicit pattern specified with -e or
|
||||
@ -732,6 +792,14 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
opt.relative = 0;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--color", arg)) {
|
||||
opt.color = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--no-color", arg)) {
|
||||
opt.color = 0;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--", arg)) {
|
||||
/* later processing wants to have this at argv[1] */
|
||||
argv--;
|
||||
@ -757,6 +825,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
}
|
||||
|
||||
if (opt.color && !opt.color_external)
|
||||
builtin_grep = 1;
|
||||
if (!opt.pattern_list)
|
||||
die("no pattern given.");
|
||||
if ((opt.regflags != REG_NEWLINE) && opt.fixed)
|
||||
|
@ -130,8 +130,7 @@ static void copy_templates(const char *template_dir)
|
||||
}
|
||||
dir = opendir(template_path);
|
||||
if (!dir) {
|
||||
fprintf(stderr, "warning: templates not found %s\n",
|
||||
template_dir);
|
||||
warning("templates not found %s", template_dir);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -144,8 +143,8 @@ static void copy_templates(const char *template_dir)
|
||||
|
||||
if (repository_format_version &&
|
||||
repository_format_version != GIT_REPO_VERSION) {
|
||||
fprintf(stderr, "warning: not copying templates of "
|
||||
"a wrong format version %d from '%s'\n",
|
||||
warning("not copying templates of "
|
||||
"a wrong format version %d from '%s'",
|
||||
repository_format_version,
|
||||
template_dir);
|
||||
closedir(dir);
|
||||
|
241
builtin-log.c
241
builtin-log.c
@ -17,6 +17,7 @@
|
||||
#include "run-command.h"
|
||||
#include "shortlog.h"
|
||||
#include "remote.h"
|
||||
#include "string-list.h"
|
||||
|
||||
/* Set a default date-time format for git log ("log.date" config variable) */
|
||||
static const char *default_date_mode = NULL;
|
||||
@ -416,18 +417,13 @@ int cmd_log(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
|
||||
/* format-patch */
|
||||
#define FORMAT_PATCH_NAME_MAX 64
|
||||
|
||||
static int istitlechar(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9') || c == '.' || c == '_';
|
||||
}
|
||||
|
||||
static const char *fmt_patch_suffix = ".patch";
|
||||
static int numbered = 0;
|
||||
static int auto_number = 1;
|
||||
|
||||
static char *default_attach = NULL;
|
||||
|
||||
static char **extra_hdr;
|
||||
static int extra_hdr_nr;
|
||||
static int extra_hdr_alloc;
|
||||
@ -459,6 +455,11 @@ static void add_header(const char *value)
|
||||
extra_hdr[extra_hdr_nr++] = xstrndup(value, len);
|
||||
}
|
||||
|
||||
#define THREAD_SHALLOW 1
|
||||
#define THREAD_DEEP 2
|
||||
static int thread = 0;
|
||||
static int do_signoff = 0;
|
||||
|
||||
static int git_format_config(const char *var, const char *value, void *cb)
|
||||
{
|
||||
if (!strcmp(var, "format.headers")) {
|
||||
@ -488,94 +489,60 @@ static int git_format_config(const char *var, const char *value, void *cb)
|
||||
auto_number = auto_number && numbered;
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "format.attach")) {
|
||||
if (value && *value)
|
||||
default_attach = xstrdup(value);
|
||||
else
|
||||
default_attach = xstrdup(git_version_string);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "format.thread")) {
|
||||
if (value && !strcasecmp(value, "deep")) {
|
||||
thread = THREAD_DEEP;
|
||||
return 0;
|
||||
}
|
||||
if (value && !strcasecmp(value, "shallow")) {
|
||||
thread = THREAD_SHALLOW;
|
||||
return 0;
|
||||
}
|
||||
thread = git_config_bool(var, value) && THREAD_SHALLOW;
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "format.signoff")) {
|
||||
do_signoff = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return git_log_config(var, value, cb);
|
||||
}
|
||||
|
||||
|
||||
static const char *get_oneline_for_filename(struct commit *commit,
|
||||
int keep_subject)
|
||||
{
|
||||
static char filename[PATH_MAX];
|
||||
char *sol;
|
||||
int len = 0;
|
||||
int suffix_len = strlen(fmt_patch_suffix) + 1;
|
||||
|
||||
sol = strstr(commit->buffer, "\n\n");
|
||||
if (!sol)
|
||||
filename[0] = '\0';
|
||||
else {
|
||||
int j, space = 0;
|
||||
|
||||
sol += 2;
|
||||
/* strip [PATCH] or [PATCH blabla] */
|
||||
if (!keep_subject && !prefixcmp(sol, "[PATCH")) {
|
||||
char *eos = strchr(sol + 6, ']');
|
||||
if (eos) {
|
||||
while (isspace(*eos))
|
||||
eos++;
|
||||
sol = eos;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0;
|
||||
j < FORMAT_PATCH_NAME_MAX - suffix_len - 5 &&
|
||||
len < sizeof(filename) - suffix_len &&
|
||||
sol[j] && sol[j] != '\n';
|
||||
j++) {
|
||||
if (istitlechar(sol[j])) {
|
||||
if (space) {
|
||||
filename[len++] = '-';
|
||||
space = 0;
|
||||
}
|
||||
filename[len++] = sol[j];
|
||||
if (sol[j] == '.')
|
||||
while (sol[j + 1] == '.')
|
||||
j++;
|
||||
} else
|
||||
space = 1;
|
||||
}
|
||||
while (filename[len - 1] == '.'
|
||||
|| filename[len - 1] == '-')
|
||||
len--;
|
||||
filename[len] = '\0';
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
static FILE *realstdout = NULL;
|
||||
static const char *output_directory = NULL;
|
||||
static int outdir_offset;
|
||||
|
||||
static int reopen_stdout(const char *oneline, int nr, int total)
|
||||
static int reopen_stdout(struct commit *commit, struct rev_info *rev)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
int len = 0;
|
||||
struct strbuf filename = STRBUF_INIT;
|
||||
int suffix_len = strlen(fmt_patch_suffix) + 1;
|
||||
|
||||
if (output_directory) {
|
||||
len = snprintf(filename, sizeof(filename), "%s",
|
||||
output_directory);
|
||||
if (len >=
|
||||
sizeof(filename) - FORMAT_PATCH_NAME_MAX - suffix_len)
|
||||
strbuf_addstr(&filename, output_directory);
|
||||
if (filename.len >=
|
||||
PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len)
|
||||
return error("name of output directory is too long");
|
||||
if (filename[len - 1] != '/')
|
||||
filename[len++] = '/';
|
||||
if (filename.buf[filename.len - 1] != '/')
|
||||
strbuf_addch(&filename, '/');
|
||||
}
|
||||
|
||||
if (!oneline)
|
||||
len += sprintf(filename + len, "%d", nr);
|
||||
else {
|
||||
len += sprintf(filename + len, "%04d-", nr);
|
||||
len += snprintf(filename + len, sizeof(filename) - len - 1
|
||||
- suffix_len, "%s", oneline);
|
||||
strcpy(filename + len, fmt_patch_suffix);
|
||||
}
|
||||
get_patch_filename(commit, rev->nr, fmt_patch_suffix, &filename);
|
||||
|
||||
fprintf(realstdout, "%s\n", filename + outdir_offset);
|
||||
if (freopen(filename, "w", stdout) == NULL)
|
||||
return error("Cannot open patch file %s",filename);
|
||||
if (!DIFF_OPT_TST(&rev->diffopt, QUIET))
|
||||
fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
|
||||
|
||||
if (freopen(filename.buf, "w", stdout) == NULL)
|
||||
return error("Cannot open patch file %s", filename.buf);
|
||||
|
||||
strbuf_release(&filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -645,7 +612,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
||||
int nr, struct commit **list, struct commit *head)
|
||||
{
|
||||
const char *committer;
|
||||
char *head_sha1;
|
||||
const char *subject_start = NULL;
|
||||
const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n";
|
||||
const char *msg;
|
||||
@ -656,21 +622,41 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
||||
const char *encoding = "utf-8";
|
||||
struct diff_options opts;
|
||||
int need_8bit_cte = 0;
|
||||
struct commit *commit = NULL;
|
||||
|
||||
if (rev->commit_format != CMIT_FMT_EMAIL)
|
||||
die("Cover letter needs email format");
|
||||
|
||||
if (!use_stdout && reopen_stdout(numbered_files ?
|
||||
NULL : "cover-letter", 0, rev->total))
|
||||
committer = git_committer_info(0);
|
||||
|
||||
if (!numbered_files) {
|
||||
/*
|
||||
* We fake a commit for the cover letter so we get the filename
|
||||
* desired.
|
||||
*/
|
||||
commit = xcalloc(1, sizeof(*commit));
|
||||
commit->buffer = xmalloc(400);
|
||||
snprintf(commit->buffer, 400,
|
||||
"tree 0000000000000000000000000000000000000000\n"
|
||||
"parent %s\n"
|
||||
"author %s\n"
|
||||
"committer %s\n\n"
|
||||
"cover letter\n",
|
||||
sha1_to_hex(head->object.sha1), committer, committer);
|
||||
}
|
||||
|
||||
if (!use_stdout && reopen_stdout(commit, rev))
|
||||
return;
|
||||
|
||||
head_sha1 = sha1_to_hex(head->object.sha1);
|
||||
if (commit) {
|
||||
|
||||
log_write_email_headers(rev, head_sha1, &subject_start, &extra_headers,
|
||||
free(commit->buffer);
|
||||
free(commit);
|
||||
}
|
||||
|
||||
log_write_email_headers(rev, head, &subject_start, &extra_headers,
|
||||
&need_8bit_cte);
|
||||
|
||||
committer = git_committer_info(0);
|
||||
|
||||
msg = body;
|
||||
pp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822,
|
||||
encoding);
|
||||
@ -766,7 +752,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
int numbered_files = 0; /* _just_ numbers */
|
||||
int subject_prefix = 0;
|
||||
int ignore_if_in_upstream = 0;
|
||||
int thread = 0;
|
||||
int cover_letter = 0;
|
||||
int boundary_count = 0;
|
||||
int no_binary_diff = 0;
|
||||
@ -787,6 +772,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
|
||||
rev.subject_prefix = fmt_patch_subject_prefix;
|
||||
|
||||
if (default_attach) {
|
||||
rev.mime_boundary = default_attach;
|
||||
rev.no_inline = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the arguments before setup_revisions(), or something
|
||||
* like "git format-patch -o a123 HEAD^.." may fail; a123 is
|
||||
@ -833,13 +823,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
else if (!strcmp(argv[i], "--signoff") ||
|
||||
!strcmp(argv[i], "-s")) {
|
||||
const char *committer;
|
||||
const char *endpos;
|
||||
committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
|
||||
endpos = strchr(committer, '>');
|
||||
if (!endpos)
|
||||
die("bogus committer info %s", committer);
|
||||
add_signoff = xmemdupz(committer, endpos - committer + 1);
|
||||
do_signoff = 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--attach")) {
|
||||
rev.mime_boundary = git_version_string;
|
||||
@ -849,6 +833,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
rev.mime_boundary = argv[i] + 9;
|
||||
rev.no_inline = 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--no-attach")) {
|
||||
rev.mime_boundary = NULL;
|
||||
rev.no_inline = 0;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--inline")) {
|
||||
rev.mime_boundary = git_version_string;
|
||||
rev.no_inline = 0;
|
||||
@ -859,8 +847,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
|
||||
ignore_if_in_upstream = 1;
|
||||
else if (!strcmp(argv[i], "--thread"))
|
||||
thread = 1;
|
||||
else if (!strcmp(argv[i], "--thread")
|
||||
|| !strcmp(argv[i], "--thread=shallow"))
|
||||
thread = THREAD_SHALLOW;
|
||||
else if (!strcmp(argv[i], "--thread=deep"))
|
||||
thread = THREAD_DEEP;
|
||||
else if (!strcmp(argv[i], "--no-thread"))
|
||||
thread = 0;
|
||||
else if (!prefixcmp(argv[i], "--in-reply-to="))
|
||||
in_reply_to = argv[i] + 14;
|
||||
else if (!strcmp(argv[i], "--in-reply-to")) {
|
||||
@ -877,11 +870,23 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
cover_letter = 1;
|
||||
else if (!strcmp(argv[i], "--no-binary"))
|
||||
no_binary_diff = 1;
|
||||
else if (!prefixcmp(argv[i], "--add-header="))
|
||||
add_header(argv[i] + 13);
|
||||
else
|
||||
argv[j++] = argv[i];
|
||||
}
|
||||
argc = j;
|
||||
|
||||
if (do_signoff) {
|
||||
const char *committer;
|
||||
const char *endpos;
|
||||
committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
|
||||
endpos = strchr(committer, '>');
|
||||
if (!endpos)
|
||||
die("bogus committer info %s", committer);
|
||||
add_signoff = xmemdupz(committer, endpos - committer + 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < extra_hdr_nr; i++) {
|
||||
strbuf_addstr(&buf, extra_hdr[i]);
|
||||
strbuf_addch(&buf, '\n');
|
||||
@ -1009,8 +1014,14 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
numbered = 1;
|
||||
if (numbered)
|
||||
rev.total = total + start_number - 1;
|
||||
if (in_reply_to)
|
||||
rev.ref_message_id = clean_message_id(in_reply_to);
|
||||
if (in_reply_to || thread || cover_letter)
|
||||
rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
|
||||
if (in_reply_to) {
|
||||
const char *msgid = clean_message_id(in_reply_to);
|
||||
string_list_append(msgid, rev.ref_message_ids);
|
||||
}
|
||||
rev.numbered_files = numbered_files;
|
||||
rev.patch_suffix = fmt_patch_suffix;
|
||||
if (cover_letter) {
|
||||
if (thread)
|
||||
gen_message_id(&rev, "cover");
|
||||
@ -1029,21 +1040,39 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
/* Have we already had a message ID? */
|
||||
if (rev.message_id) {
|
||||
/*
|
||||
* If we've got the ID to be a reply
|
||||
* to, discard the current ID;
|
||||
* otherwise, make everything a reply
|
||||
* to that.
|
||||
* For deep threading: make every mail
|
||||
* a reply to the previous one, no
|
||||
* matter what other options are set.
|
||||
*
|
||||
* For shallow threading:
|
||||
*
|
||||
* Without --cover-letter and
|
||||
* --in-reply-to, make every mail a
|
||||
* reply to the one before.
|
||||
*
|
||||
* With --in-reply-to but no
|
||||
* --cover-letter, make every mail a
|
||||
* reply to the <reply-to>.
|
||||
*
|
||||
* With --cover-letter, make every
|
||||
* mail but the cover letter a reply
|
||||
* to the cover letter. The cover
|
||||
* letter is a reply to the
|
||||
* --in-reply-to, if specified.
|
||||
*/
|
||||
if (rev.ref_message_id)
|
||||
if (thread == THREAD_SHALLOW
|
||||
&& rev.ref_message_ids->nr > 0
|
||||
&& (!cover_letter || rev.nr > 1))
|
||||
free(rev.message_id);
|
||||
else
|
||||
rev.ref_message_id = rev.message_id;
|
||||
string_list_append(rev.message_id,
|
||||
rev.ref_message_ids);
|
||||
}
|
||||
gen_message_id(&rev, sha1_to_hex(commit->object.sha1));
|
||||
}
|
||||
if (!use_stdout && reopen_stdout(numbered_files ? NULL :
|
||||
get_oneline_for_filename(commit, keep_subject),
|
||||
rev.nr, rev.total))
|
||||
|
||||
if (!use_stdout && reopen_stdout(numbered_files ? NULL : commit,
|
||||
&rev))
|
||||
die("Failed to create output files");
|
||||
shown = log_tree_commit(&rev, commit);
|
||||
free(commit->buffer);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "dir.h"
|
||||
#include "builtin.h"
|
||||
#include "tree.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static int abbrev;
|
||||
static int show_deleted;
|
||||
@ -28,6 +29,7 @@ static const char **pathspec;
|
||||
static int error_unmatch;
|
||||
static char *ps_matched;
|
||||
static const char *with_tree;
|
||||
static int exc_given;
|
||||
|
||||
static const char *tag_cached = "";
|
||||
static const char *tag_unmerged = "";
|
||||
@ -174,7 +176,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
|
||||
for (i = 0; i < active_nr; i++) {
|
||||
struct cache_entry *ce = active_cache[i];
|
||||
int dtype = ce_to_dtype(ce);
|
||||
if (excluded(dir, ce->name, &dtype) != dir->show_ignored)
|
||||
if (excluded(dir, ce->name, &dtype) !=
|
||||
!!(dir->flags & DIR_SHOW_IGNORED))
|
||||
continue;
|
||||
if (show_unmerged && !ce_stage(ce))
|
||||
continue;
|
||||
@ -189,7 +192,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
|
||||
struct stat st;
|
||||
int err;
|
||||
int dtype = ce_to_dtype(ce);
|
||||
if (excluded(dir, ce->name, &dtype) != dir->show_ignored)
|
||||
if (excluded(dir, ce->name, &dtype) !=
|
||||
!!(dir->flags & DIR_SHOW_IGNORED))
|
||||
continue;
|
||||
if (ce->ce_flags & CE_UPDATE)
|
||||
continue;
|
||||
@ -374,157 +378,139 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_
|
||||
return errors;
|
||||
}
|
||||
|
||||
static const char ls_files_usage[] =
|
||||
"git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
|
||||
"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
|
||||
"[ --exclude-per-directory=<filename> ] [--exclude-standard] "
|
||||
"[--full-name] [--abbrev] [--] [<file>]*";
|
||||
static const char * const ls_files_usage[] = {
|
||||
"git ls-files [options] [<file>]*",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int option_parse_z(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
{
|
||||
line_terminator = unset ? '\n' : '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int option_parse_exclude(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
{
|
||||
struct exclude_list *list = opt->value;
|
||||
|
||||
exc_given = 1;
|
||||
add_exclude(arg, "", 0, list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int option_parse_exclude_from(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
{
|
||||
struct dir_struct *dir = opt->value;
|
||||
|
||||
exc_given = 1;
|
||||
add_excludes_from_file(dir, arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int option_parse_exclude_standard(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
{
|
||||
struct dir_struct *dir = opt->value;
|
||||
|
||||
exc_given = 1;
|
||||
setup_standard_excludes(dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_ls_files(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i;
|
||||
int exc_given = 0, require_work_tree = 0;
|
||||
int require_work_tree = 0, show_tag = 0;
|
||||
struct dir_struct dir;
|
||||
struct option builtin_ls_files_options[] = {
|
||||
{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
|
||||
"paths are separated with NUL character",
|
||||
PARSE_OPT_NOARG, option_parse_z },
|
||||
OPT_BOOLEAN('t', NULL, &show_tag,
|
||||
"identify the file status with tags"),
|
||||
OPT_BOOLEAN('v', NULL, &show_valid_bit,
|
||||
"use lowercase letters for 'assume unchanged' files"),
|
||||
OPT_BOOLEAN('c', "cached", &show_cached,
|
||||
"show cached files in the output (default)"),
|
||||
OPT_BOOLEAN('d', "deleted", &show_deleted,
|
||||
"show deleted files in the output"),
|
||||
OPT_BOOLEAN('m', "modified", &show_modified,
|
||||
"show modified files in the output"),
|
||||
OPT_BOOLEAN('o', "others", &show_others,
|
||||
"show other files in the output"),
|
||||
OPT_BIT('i', "ignored", &dir.flags,
|
||||
"show ignored files in the output",
|
||||
DIR_SHOW_IGNORED),
|
||||
OPT_BOOLEAN('s', "stage", &show_stage,
|
||||
"show staged contents' object name in the output"),
|
||||
OPT_BOOLEAN('k', "killed", &show_killed,
|
||||
"show files on the filesystem that need to be removed"),
|
||||
OPT_BIT(0, "directory", &dir.flags,
|
||||
"show 'other' directories' name only",
|
||||
DIR_SHOW_OTHER_DIRECTORIES),
|
||||
OPT_BIT(0, "no-empty-directory", &dir.flags,
|
||||
"don't show empty directories",
|
||||
DIR_HIDE_EMPTY_DIRECTORIES),
|
||||
OPT_BOOLEAN('u', "unmerged", &show_unmerged,
|
||||
"show unmerged files in the output"),
|
||||
{ OPTION_CALLBACK, 'x', "exclude", &dir.exclude_list[EXC_CMDL], "pattern",
|
||||
"skip files matching pattern",
|
||||
0, option_parse_exclude },
|
||||
{ OPTION_CALLBACK, 'X', "exclude-from", &dir, "file",
|
||||
"exclude patterns are read from <file>",
|
||||
0, option_parse_exclude_from },
|
||||
OPT_STRING(0, "exclude-per-directory", &dir.exclude_per_dir, "file",
|
||||
"read additional per-directory exclude patterns in <file>"),
|
||||
{ OPTION_CALLBACK, 0, "exclude-standard", &dir, NULL,
|
||||
"add the standard git exclusions",
|
||||
PARSE_OPT_NOARG, option_parse_exclude_standard },
|
||||
{ OPTION_SET_INT, 0, "full-name", &prefix_offset, NULL,
|
||||
"make the output relative to the project top directory",
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL },
|
||||
OPT_BOOLEAN(0, "error-unmatch", &error_unmatch,
|
||||
"if any <file> is not in the index, treat this as an error"),
|
||||
OPT_STRING(0, "with-tree", &with_tree, "tree-ish",
|
||||
"pretend that paths removed since <tree-ish> are still present"),
|
||||
OPT__ABBREV(&abbrev),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
memset(&dir, 0, sizeof(dir));
|
||||
if (prefix)
|
||||
prefix_offset = strlen(prefix);
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
|
||||
if (!strcmp(arg, "--")) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
if (!strcmp(arg, "-z")) {
|
||||
line_terminator = 0;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-t") || !strcmp(arg, "-v")) {
|
||||
tag_cached = "H ";
|
||||
tag_unmerged = "M ";
|
||||
tag_removed = "R ";
|
||||
tag_modified = "C ";
|
||||
tag_other = "? ";
|
||||
tag_killed = "K ";
|
||||
if (arg[1] == 'v')
|
||||
show_valid_bit = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-c") || !strcmp(arg, "--cached")) {
|
||||
show_cached = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-d") || !strcmp(arg, "--deleted")) {
|
||||
show_deleted = 1;
|
||||
require_work_tree = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-m") || !strcmp(arg, "--modified")) {
|
||||
show_modified = 1;
|
||||
require_work_tree = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-o") || !strcmp(arg, "--others")) {
|
||||
show_others = 1;
|
||||
require_work_tree = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-i") || !strcmp(arg, "--ignored")) {
|
||||
dir.show_ignored = 1;
|
||||
require_work_tree = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-s") || !strcmp(arg, "--stage")) {
|
||||
show_stage = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-k") || !strcmp(arg, "--killed")) {
|
||||
show_killed = 1;
|
||||
require_work_tree = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--directory")) {
|
||||
dir.show_other_directories = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--no-empty-directory")) {
|
||||
dir.hide_empty_directories = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-u") || !strcmp(arg, "--unmerged")) {
|
||||
/* There's no point in showing unmerged unless
|
||||
* you also show the stage information.
|
||||
*/
|
||||
show_stage = 1;
|
||||
show_unmerged = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-x") && i+1 < argc) {
|
||||
exc_given = 1;
|
||||
add_exclude(argv[++i], "", 0, &dir.exclude_list[EXC_CMDL]);
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--exclude=")) {
|
||||
exc_given = 1;
|
||||
add_exclude(arg+10, "", 0, &dir.exclude_list[EXC_CMDL]);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-X") && i+1 < argc) {
|
||||
exc_given = 1;
|
||||
add_excludes_from_file(&dir, argv[++i]);
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--exclude-from=")) {
|
||||
exc_given = 1;
|
||||
add_excludes_from_file(&dir, arg+15);
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--exclude-per-directory=")) {
|
||||
exc_given = 1;
|
||||
dir.exclude_per_dir = arg + 24;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--exclude-standard")) {
|
||||
exc_given = 1;
|
||||
setup_standard_excludes(&dir);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--full-name")) {
|
||||
prefix_offset = 0;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--error-unmatch")) {
|
||||
error_unmatch = 1;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--with-tree=")) {
|
||||
with_tree = arg + 12;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--abbrev=")) {
|
||||
abbrev = strtoul(arg+9, NULL, 10);
|
||||
if (abbrev && abbrev < MINIMUM_ABBREV)
|
||||
abbrev = MINIMUM_ABBREV;
|
||||
else if (abbrev > 40)
|
||||
abbrev = 40;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--abbrev")) {
|
||||
abbrev = DEFAULT_ABBREV;
|
||||
continue;
|
||||
}
|
||||
if (*arg == '-')
|
||||
usage(ls_files_usage);
|
||||
break;
|
||||
argc = parse_options(argc, argv, builtin_ls_files_options,
|
||||
ls_files_usage, 0);
|
||||
if (show_tag || show_valid_bit) {
|
||||
tag_cached = "H ";
|
||||
tag_unmerged = "M ";
|
||||
tag_removed = "R ";
|
||||
tag_modified = "C ";
|
||||
tag_other = "? ";
|
||||
tag_killed = "K ";
|
||||
}
|
||||
if (show_modified || show_others || show_deleted || (dir.flags & DIR_SHOW_IGNORED) || show_killed)
|
||||
require_work_tree = 1;
|
||||
if (show_unmerged)
|
||||
/*
|
||||
* There's no point in showing unmerged unless
|
||||
* you also show the stage information.
|
||||
*/
|
||||
show_stage = 1;
|
||||
if (dir.exclude_per_dir)
|
||||
exc_given = 1;
|
||||
|
||||
if (require_work_tree && !is_inside_work_tree())
|
||||
setup_work_tree();
|
||||
|
||||
pathspec = get_pathspec(prefix, argv + i);
|
||||
pathspec = get_pathspec(prefix, argv);
|
||||
|
||||
/* be nice with submodule patsh ending in a slash */
|
||||
read_cache();
|
||||
@ -543,7 +529,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
|
||||
ps_matched = xcalloc(1, num);
|
||||
}
|
||||
|
||||
if (dir.show_ignored && !exc_given) {
|
||||
if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given) {
|
||||
fprintf(stderr, "%s: --ignored needs some exclude pattern\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
|
@ -60,7 +60,6 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
|
||||
{
|
||||
int retval = 0;
|
||||
const char *type = blob_type;
|
||||
unsigned long size;
|
||||
|
||||
if (S_ISGITLINK(mode)) {
|
||||
/*
|
||||
@ -90,17 +89,20 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
|
||||
|
||||
if (!(ls_options & LS_NAME_ONLY)) {
|
||||
if (ls_options & LS_SHOW_SIZE) {
|
||||
char size_text[24];
|
||||
if (!strcmp(type, blob_type)) {
|
||||
sha1_object_info(sha1, &size);
|
||||
printf("%06o %s %s %7lu\t", mode, type,
|
||||
abbrev ? find_unique_abbrev(sha1, abbrev)
|
||||
: sha1_to_hex(sha1),
|
||||
size);
|
||||
unsigned long size;
|
||||
if (sha1_object_info(sha1, &size) == OBJ_BAD)
|
||||
strcpy(size_text, "BAD");
|
||||
else
|
||||
snprintf(size_text, sizeof(size_text),
|
||||
"%lu", size);
|
||||
} else
|
||||
printf("%06o %s %s %7c\t", mode, type,
|
||||
abbrev ? find_unique_abbrev(sha1, abbrev)
|
||||
: sha1_to_hex(sha1),
|
||||
'-');
|
||||
strcpy(size_text, "-");
|
||||
printf("%06o %s %s %7s\t", mode, type,
|
||||
abbrev ? find_unique_abbrev(sha1, abbrev)
|
||||
: sha1_to_hex(sha1),
|
||||
size_text);
|
||||
} else
|
||||
printf("%06o %s %s\t", mode, type,
|
||||
abbrev ? find_unique_abbrev(sha1, abbrev)
|
||||
|
@ -537,7 +537,6 @@ static int decode_header_bq(struct strbuf *it)
|
||||
*/
|
||||
strbuf_add(&outbuf, in, ep - in);
|
||||
}
|
||||
in = ep;
|
||||
}
|
||||
/* E.g.
|
||||
* ep : "=?iso-2022-jp?B?GyR...?= foo"
|
||||
|
@ -360,9 +360,8 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
||||
const char *ptr;
|
||||
int len, early;
|
||||
|
||||
len = strlen(remote);
|
||||
if (interpret_nth_last_branch(remote, &bname) == len)
|
||||
remote = bname.buf;
|
||||
strbuf_branchname(&bname, remote);
|
||||
remote = bname.buf;
|
||||
|
||||
memset(branch_head, 0, sizeof(branch_head));
|
||||
remote_head = peel_to_type(remote, 0, NULL, OBJ_COMMIT);
|
||||
@ -636,7 +635,7 @@ static int checkout_fast_forward(unsigned char *head, unsigned char *remote)
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
memset(&t, 0, sizeof(t));
|
||||
memset(&dir, 0, sizeof(dir));
|
||||
dir.show_ignored = 1;
|
||||
dir.flags |= DIR_SHOW_IGNORED;
|
||||
dir.exclude_per_dir = ".gitignore";
|
||||
opts.dir = &dir;
|
||||
|
||||
|
@ -1612,7 +1612,7 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
|
||||
return;
|
||||
}
|
||||
if (progress > pack_to_stdout)
|
||||
fprintf(stderr, "Delta compression using %d threads.\n",
|
||||
fprintf(stderr, "Delta compression using up to %d threads.\n",
|
||||
delta_search_threads);
|
||||
|
||||
/* Partition the work amongst work threads. */
|
||||
@ -1901,17 +1901,19 @@ static void read_object_list_from_stdin(void)
|
||||
|
||||
#define OBJECT_ADDED (1u<<20)
|
||||
|
||||
static void show_commit(struct commit *commit)
|
||||
static void show_commit(struct commit *commit, void *data)
|
||||
{
|
||||
add_object_entry(commit->object.sha1, OBJ_COMMIT, NULL, 0);
|
||||
commit->object.flags |= OBJECT_ADDED;
|
||||
}
|
||||
|
||||
static void show_object(struct object_array_entry *p)
|
||||
static void show_object(struct object_array_entry *p, void *data)
|
||||
{
|
||||
add_preferred_base_object(p->name);
|
||||
add_object_entry(p->item->sha1, p->item->type, p->name, 0);
|
||||
p->item->flags |= OBJECT_ADDED;
|
||||
free((char *)p->name);
|
||||
p->name = NULL;
|
||||
}
|
||||
|
||||
static void show_edge(struct commit *commit)
|
||||
@ -1966,11 +1968,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
|
||||
const unsigned char *sha1;
|
||||
struct object *o;
|
||||
|
||||
for (i = 0; i < revs->num_ignore_packed; i++) {
|
||||
if (matches_pack_name(p, revs->ignore_packed[i]))
|
||||
break;
|
||||
}
|
||||
if (revs->num_ignore_packed <= i)
|
||||
if (!p->pack_local || p->pack_keep)
|
||||
continue;
|
||||
if (open_pack_index(p))
|
||||
die("cannot open pack index");
|
||||
@ -1999,6 +1997,29 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
|
||||
free(in_pack.array);
|
||||
}
|
||||
|
||||
static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1)
|
||||
{
|
||||
static struct packed_git *last_found = (void *)1;
|
||||
struct packed_git *p;
|
||||
|
||||
p = (last_found != (void *)1) ? last_found : packed_git;
|
||||
|
||||
while (p) {
|
||||
if ((!p->pack_local || p->pack_keep) &&
|
||||
find_pack_entry_one(sha1, p)) {
|
||||
last_found = p;
|
||||
return 1;
|
||||
}
|
||||
if (p == last_found)
|
||||
p = packed_git;
|
||||
else
|
||||
p = p->next;
|
||||
if (p == last_found)
|
||||
p = p->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void loosen_unused_packed_objects(struct rev_info *revs)
|
||||
{
|
||||
struct packed_git *p;
|
||||
@ -2006,11 +2027,7 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
|
||||
const unsigned char *sha1;
|
||||
|
||||
for (p = packed_git; p; p = p->next) {
|
||||
for (i = 0; i < revs->num_ignore_packed; i++) {
|
||||
if (matches_pack_name(p, revs->ignore_packed[i]))
|
||||
break;
|
||||
}
|
||||
if (revs->num_ignore_packed <= i)
|
||||
if (!p->pack_local || p->pack_keep)
|
||||
continue;
|
||||
|
||||
if (open_pack_index(p))
|
||||
@ -2018,7 +2035,8 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
|
||||
|
||||
for (i = 0; i < p->num_objects; i++) {
|
||||
sha1 = nth_packed_object_sha1(p, i);
|
||||
if (!locate_object_entry(sha1))
|
||||
if (!locate_object_entry(sha1) &&
|
||||
!has_sha1_pack_kept_or_nonlocal(sha1))
|
||||
if (force_object_loose(sha1, p->mtime))
|
||||
die("unable to force loose object");
|
||||
}
|
||||
@ -2055,7 +2073,7 @@ static void get_object_list(int ac, const char **av)
|
||||
if (prepare_revision_walk(&revs))
|
||||
die("revision walk setup failed");
|
||||
mark_edges_uninteresting(revs.commits, &revs, show_edge);
|
||||
traverse_commit_list(&revs, show_commit, show_object);
|
||||
traverse_commit_list(&revs, show_commit, show_object, NULL);
|
||||
|
||||
if (keep_unreachable)
|
||||
add_objects_in_unpacked_packs(&revs);
|
||||
@ -2208,7 +2226,6 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--unpacked", arg) ||
|
||||
!prefixcmp(arg, "--unpacked=") ||
|
||||
!strcmp("--reflog", arg) ||
|
||||
!strcmp("--all", arg)) {
|
||||
use_internal_rev_list = 1;
|
||||
|
@ -23,7 +23,7 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts)
|
||||
memcpy(hex+2, de->d_name, 38);
|
||||
if (get_sha1_hex(hex, sha1))
|
||||
continue;
|
||||
if (!has_sha1_pack(sha1, NULL))
|
||||
if (!has_sha1_pack(sha1))
|
||||
continue;
|
||||
memcpy(pathname + len, de->d_name, 38);
|
||||
if (opts & DRY_RUN)
|
||||
|
@ -48,6 +48,71 @@ static void set_refspecs(const char **refs, int nr)
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_push_tracking(void)
|
||||
{
|
||||
struct strbuf refspec = STRBUF_INIT;
|
||||
struct branch *branch = branch_get(NULL);
|
||||
if (!branch)
|
||||
die("You are not currently on a branch.");
|
||||
if (!branch->merge_nr)
|
||||
die("The current branch %s is not tracking anything.",
|
||||
branch->name);
|
||||
if (branch->merge_nr != 1)
|
||||
die("The current branch %s is tracking multiple branches, "
|
||||
"refusing to push.", branch->name);
|
||||
strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
|
||||
add_refspec(refspec.buf);
|
||||
}
|
||||
|
||||
static const char *warn_unconfigured_push_msg[] = {
|
||||
"You did not specify any refspecs to push, and the current remote",
|
||||
"has not configured any push refspecs. The default action in this",
|
||||
"case is to push all matching refspecs, that is, all branches",
|
||||
"that exist both locally and remotely will be updated. This may",
|
||||
"not necessarily be what you want to happen.",
|
||||
"",
|
||||
"You can specify what action you want to take in this case, and",
|
||||
"avoid seeing this message again, by configuring 'push.default' to:",
|
||||
" 'nothing' : Do not push anything",
|
||||
" 'matching' : Push all matching branches (default)",
|
||||
" 'tracking' : Push the current branch to whatever it is tracking",
|
||||
" 'current' : Push the current branch"
|
||||
};
|
||||
|
||||
static void warn_unconfigured_push(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(warn_unconfigured_push_msg); i++)
|
||||
warning("%s", warn_unconfigured_push_msg[i]);
|
||||
}
|
||||
|
||||
static void setup_default_push_refspecs(void)
|
||||
{
|
||||
git_config(git_default_config, NULL);
|
||||
switch (push_default) {
|
||||
case PUSH_DEFAULT_UNSPECIFIED:
|
||||
warn_unconfigured_push();
|
||||
/* fallthrough */
|
||||
|
||||
case PUSH_DEFAULT_MATCHING:
|
||||
add_refspec(":");
|
||||
break;
|
||||
|
||||
case PUSH_DEFAULT_TRACKING:
|
||||
setup_push_tracking();
|
||||
break;
|
||||
|
||||
case PUSH_DEFAULT_CURRENT:
|
||||
add_refspec("HEAD");
|
||||
break;
|
||||
|
||||
case PUSH_DEFAULT_NOTHING:
|
||||
die("You didn't specify any refspecs to push, and "
|
||||
"push.default is \"nothing\".");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int do_push(const char *repo, int flags)
|
||||
{
|
||||
int i, errs;
|
||||
@ -79,11 +144,12 @@ static int do_push(const char *repo, int flags)
|
||||
return error("--all and --mirror are incompatible");
|
||||
}
|
||||
|
||||
if (!refspec
|
||||
&& !(flags & TRANSPORT_PUSH_ALL)
|
||||
&& remote->push_refspec_nr) {
|
||||
refspec = remote->push_refspec;
|
||||
refspec_nr = remote->push_refspec_nr;
|
||||
if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
|
||||
if (remote->push_refspec_nr) {
|
||||
refspec = remote->push_refspec;
|
||||
refspec_nr = remote->push_refspec_nr;
|
||||
} else if (!(flags & TRANSPORT_PUSH_MIRROR))
|
||||
setup_default_push_refspecs();
|
||||
}
|
||||
errs = 0;
|
||||
for (i = 0; i < remote->url_nr; i++) {
|
||||
|
@ -170,7 +170,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
|
||||
die("more than one --exclude-per-directory are given.");
|
||||
|
||||
dir = xcalloc(1, sizeof(*opts.dir));
|
||||
dir->show_ignored = 1;
|
||||
dir->flags |= DIR_SHOW_IGNORED;
|
||||
dir->exclude_per_dir = arg + 24;
|
||||
opts.dir = dir;
|
||||
/* We do not need to nor want to do read-directory
|
||||
|
@ -675,7 +675,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
|
||||
setup_path();
|
||||
|
||||
if (!enter_repo(dir, 0))
|
||||
die("'%s': unable to chdir or not a git archive", dir);
|
||||
die("'%s' does not appear to be a git repository", dir);
|
||||
|
||||
if (is_repository_shallow())
|
||||
die("attempt to push into a shallow repository");
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user