From: Junio C Hamano Date: Tue, 13 Jun 2006 17:53:41 +0000 (-0700) Subject: Merge git://git.kernel.org/pub/scm/gitk/gitk X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=b642d9ef643371990c0a921836f2a074d48ce1b3;hp=2e1ded44f709ddc95c5e8a87e0d98127979115fe;p=git.git Merge git://git.kernel.org/pub/scm/gitk/gitk * git://git.kernel.org/pub/scm/gitk/gitk: [PATCH] gitk: rereadrefs needs listrefs --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..afd08762 --- /dev/null +++ b/.gitignore @@ -0,0 +1,138 @@ +GIT-VERSION-FILE +git +git-add +git-am +git-annotate +git-apply +git-applymbox +git-applypatch +git-archimport +git-bisect +git-branch +git-cat-file +git-check-ref-format +git-checkout +git-checkout-index +git-cherry +git-cherry-pick +git-clean +git-clone +git-clone-pack +git-commit +git-commit-tree +git-convert-objects +git-count-objects +git-cvsexportcommit +git-cvsimport +git-cvsserver +git-daemon +git-diff +git-diff-files +git-diff-index +git-diff-stages +git-diff-tree +git-describe +git-fetch +git-fetch-pack +git-findtags +git-fmt-merge-msg +git-format-patch +git-fsck-objects +git-get-tar-commit-id +git-grep +git-hash-object +git-http-fetch +git-http-push +git-imap-send +git-index-pack +git-init-db +git-local-fetch +git-log +git-lost-found +git-ls-files +git-ls-remote +git-ls-tree +git-mailinfo +git-mailsplit +git-merge +git-merge-base +git-merge-index +git-merge-tree +git-merge-octopus +git-merge-one-file +git-merge-ours +git-merge-recursive +git-merge-resolve +git-merge-stupid +git-mktag +git-mktree +git-name-rev +git-mv +git-pack-redundant +git-pack-objects +git-parse-remote +git-patch-id +git-peek-remote +git-prune +git-prune-packed +git-pull +git-push +git-quiltimport +git-read-tree +git-rebase +git-receive-pack +git-relink +git-repack +git-repo-config +git-request-pull +git-rerere +git-reset +git-resolve +git-rev-list +git-rev-parse +git-revert +git-rm +git-send-email +git-send-pack +git-sh-setup +git-shell +git-shortlog +git-show +git-show-branch +git-show-index +git-ssh-fetch +git-ssh-pull +git-ssh-push +git-ssh-upload +git-status +git-stripspace +git-svnimport +git-symbolic-ref +git-tag +git-tar-tree +git-unpack-file +git-unpack-objects +git-update-index +git-update-ref +git-update-server-info +git-upload-pack +git-upload-tar +git-var +git-verify-pack +git-verify-tag +git-whatchanged +git-write-tree +git-core-*/?* +test-date +test-delta +test-dump-cache-tree +common-cmds.h +*.tar.gz +*.dsc +*.deb +git-core.spec +*.exe +*.[ao] +*.py[co] +config.mak +git-blame diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..6ff87c46 --- /dev/null +++ b/COPYING @@ -0,0 +1,361 @@ + + Note that the only valid version of the GPL as far as this project + is concerned is _this_ particular version of the license (ie v2, not + v2.2 or v3.x or whatever), unless explicitly otherwise stated. + + HOWEVER, in order to allow a migration to GPLv3 if that seems like + a good idea, I also ask that people involved with the project make + their preferences known. In particular, if you trust me to make that + decision, you might note so in your copyright message, ie something + like + + This file is licensed under the GPL v2, or a later version + at the discretion of Linus. + + might avoid issues. But we can also just decide to synchronize and + contact all copyright holders on record if/when the occasion arises. + + Linus Torvalds + +---------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Documentation/.gitignore b/Documentation/.gitignore new file mode 100644 index 00000000..c87c61af --- /dev/null +++ b/Documentation/.gitignore @@ -0,0 +1,7 @@ +*.xml +*.html +*.1 +*.7 +howto-index.txt +doc.dep +README diff --git a/Documentation/Makefile b/Documentation/Makefile new file mode 100644 index 00000000..2b0efe79 --- /dev/null +++ b/Documentation/Makefile @@ -0,0 +1,111 @@ +MAN1_TXT= \ + $(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \ + $(wildcard git-*.txt)) \ + gitk.txt +MAN7_TXT=git.txt + +DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT)) + +ARTICLES = tutorial +ARTICLES += tutorial-2 +ARTICLES += core-tutorial +ARTICLES += cvs-migration +ARTICLES += diffcore +ARTICLES += howto-index +ARTICLES += repository-layout +ARTICLES += hooks +ARTICLES += everyday +ARTICLES += git-tools +# with their own formatting rules. +SP_ARTICLES = glossary howto/revert-branch-rebase + +DOC_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES)) + +DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT)) +DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT)) + +prefix?=$(HOME) +bin=$(prefix)/bin +mandir=$(prefix)/man +man1=$(mandir)/man1 +man7=$(mandir)/man7 +# DESTDIR= + +INSTALL?=install + +# +# Please note that there is a minor bug in asciidoc. +# The version after 6.0.3 _will_ include the patch found here: +# http://marc.theaimsgroup.com/?l=git&m=111558757202243&w=2 +# +# Until that version is released you may have to apply the patch +# yourself - yes, all 6 characters of it! +# + +all: html man + +html: $(DOC_HTML) + + +man: man1 man7 +man1: $(DOC_MAN1) +man7: $(DOC_MAN7) + +install: man + $(INSTALL) -d -m755 $(DESTDIR)$(man1) $(DESTDIR)$(man7) + $(INSTALL) $(DOC_MAN1) $(DESTDIR)$(man1) + $(INSTALL) $(DOC_MAN7) $(DESTDIR)$(man7) + + +# +# Determine "include::" file references in asciidoc files. +# +doc.dep : $(wildcard *.txt) build-docdep.perl + rm -f $@+ $@ + perl ./build-docdep.perl >$@+ + mv $@+ $@ + +-include doc.dep + +git.7: README + +README: ../README + cp $< $@ + + +clean: + rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html doc.dep README + +%.html : %.txt + asciidoc -b xhtml11 -d manpage -f asciidoc.conf $< + +%.1 %.7 : %.xml + xmlto -m callouts.xsl man $< + +%.xml : %.txt + asciidoc -b docbook -d manpage -f asciidoc.conf $< + +git.html: git.txt README + +glossary.html : glossary.txt sort_glossary.pl + cat $< | \ + perl sort_glossary.pl | \ + asciidoc -b xhtml11 - > glossary.html + +howto-index.txt: howto-index.sh $(wildcard howto/*.txt) + rm -f $@+ $@ + sh ./howto-index.sh $(wildcard howto/*.txt) >$@+ + mv $@+ $@ + +$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt + asciidoc -b xhtml11 $*.txt + +WEBDOC_DEST = /pub/software/scm/git/docs + +$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt + rm -f $@+ $@ + sed -e '1,/^$$/d' $? | asciidoc -b xhtml11 - >$@+ + mv $@+ $@ + +install-webdoc : html + sh ./install-webdoc.sh $(WEBDOC_DEST) diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches new file mode 100644 index 00000000..8601949e --- /dev/null +++ b/Documentation/SubmittingPatches @@ -0,0 +1,306 @@ +I started reading over the SubmittingPatches document for Linux +kernel, primarily because I wanted to have a document similar to +it for the core GIT to make sure people understand what they are +doing when they write "Signed-off-by" line. + +But the patch submission requirements are a lot more relaxed +here on the technical/contents front, because the core GIT is +thousand times smaller ;-). So here is only the relevant bits. + + +(1) Make separate commits for logically separate changes. + +Unless your patch is really trivial, you should not be sending +out a patch that was generated between your working tree and +your commit head. Instead, always make a commit with complete +commit message and generate a series of patches from your +repository. It is a good discipline. + +Describe the technical detail of the change(s). + +If your description starts to get too long, that's a sign that you +probably need to split up your commit to finer grained pieces. + +Oh, another thing. I am picky about whitespaces. Make sure your +changes do not trigger errors with the sample pre-commit hook shipped +in templates/hooks--pre-commit. + + +(2) Generate your patch using git tools out of your commits. + +git based diff tools (git, Cogito, and StGIT included) generate +unidiff which is the preferred format. + +You do not have to be afraid to use -M option to "git diff" or +"git format-patch", if your patch involves file renames. The +receiving end can handle them just fine. + +Please make sure your patch does not include any extra files +which do not belong in a patch submission. Make sure to review +your patch after generating it, to ensure accuracy. Before +sending out, please make sure it cleanly applies to the "master" +branch head. If you are preparing a work based on "next" branch, +that is fine, but please mark it as such. + + +(3) Sending your patches. + +People on the git mailing list need to be able to read and +comment on the changes you are submitting. It is important for +a developer to be able to "quote" your changes, using standard +e-mail tools, so that they may comment on specific portions of +your code. For this reason, all patches should be submited +"inline". WARNING: Be wary of your MUAs word-wrap +corrupting your patch. Do not cut-n-paste your patch; you can +lose tabs that way if you are not careful. + +It is a common convention to prefix your subject line with +[PATCH]. This lets people easily distinguish patches from other +e-mail discussions. + +"git format-patch" command follows the best current practice to +format the body of an e-mail message. At the beginning of the +patch should come your commit message, ending with the +Signed-off-by: lines, and a line that consists of three dashes, +followed by the diffstat information and the patch itself. If +you are forwarding a patch from somebody else, optionally, at +the beginning of the e-mail message just before the commit +message starts, you can put a "From: " line to name that person. + +You often want to add additional explanation about the patch, +other than the commit message itself. Place such "cover letter" +material between the three dash lines and the diffstat. + +Do not attach the patch as a MIME attachment, compressed or not. +Do not let your e-mail client send quoted-printable. Many +popular e-mail applications will not always transmit a MIME +attachment as plain text, making it impossible to comment on +your code. A MIME attachment also takes a bit more time to +process. This does not decrease the likelihood of your +MIME-attached change being accepted, but it makes it more likely +that it will be postponed. + +Exception: If your mailer is mangling patches then someone may ask +you to re-send them using MIME, that is OK. + +Do not PGP sign your patch, at least for now. Most likely, your +maintainer or other people on the list would not have your PGP +key and would not bother obtaining it anyway. Your patch is not +judged by who you are; a good patch from an unknown origin has a +far better chance of being accepted than a patch from a known, +respected origin that is done poorly or does incorrect things. + +If you really really really really want to do a PGP signed +patch, format it as "multipart/signed", not a text/plain message +that starts with '-----BEGIN PGP SIGNED MESSAGE-----'. That is +not a text/plain, it's something else. + +Note that your maintainer does not necessarily read everything +on the git mailing list. If your patch is for discussion first, +send it "To:" the mailing list, and optionally "cc:" him. If it +is trivially correct or after the list reached a consensus, send +it "To:" the maintainer and optionally "cc:" the list. + + +(6) Sign your work + +To improve tracking of who did what, we've borrowed the +"sign-off" procedure from the Linux kernel project on patches +that are being emailed around. Although core GIT is a lot +smaller project it is a good discipline to follow it. + +The sign-off is a simple line at the end of the explanation for +the patch, which certifies that you wrote it or otherwise have +the right to pass it on as a open-source patch. The rules are +pretty simple: if you can certify the below: + + Developer's Certificate of Origin 1.1 + + By making a contribution to this project, I certify that: + + (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + + (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + + (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + + (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + +then you just add a line saying + + Signed-off-by: Random J Developer + +Some people also put extra tags at the end. They'll just be ignored for +now, but you can do this to mark internal company procedures or just +point out some special detail about the sign-off. + + +------------------------------------------------ +MUA specific hints + +Some of patches I receive or pick up from the list share common +patterns of breakage. Please make sure your MUA is set up +properly not to corrupt whitespaces. Here are two common ones +I have seen: + +* Empty context lines that do not have _any_ whitespace. + +* Non empty context lines that have one extra whitespace at the + beginning. + +One test you could do yourself if your MUA is set up correctly is: + +* Send the patch to yourself, exactly the way you would, except + To: and Cc: lines, which would not contain the list and + maintainer address. + +* Save that patch to a file in UNIX mailbox format. Call it say + a.patch. + +* Try to apply to the tip of the "master" branch from the + git.git public repository: + + $ git fetch http://kernel.org/pub/scm/git/git.git master:test-apply + $ git checkout test-apply + $ git reset --hard + $ git applymbox a.patch + +If it does not apply correctly, there can be various reasons. + +* Your patch itself does not apply cleanly. That is _bad_ but + does not have much to do with your MUA. Please rebase the + patch appropriately. + +* Your MUA corrupted your patch; applymbox would complain that + the patch does not apply. Look at .dotest/ subdirectory and + see what 'patch' file contains and check for the common + corruption patterns mentioned above. + +* While you are at it, check what are in 'info' and + 'final-commit' files as well. If what is in 'final-commit' is + not exactly what you would want to see in the commit log + message, it is very likely that your maintainer would end up + hand editing the log message when he applies your patch. + Things like "Hi, this is my first patch.\n", if you really + want to put in the patch e-mail, should come after the + three-dash line that signals the end of the commit message. + + +Pine +---- + +(Johannes Schindelin) + +I don't know how many people still use pine, but for those poor +souls it may be good to mention that the quell-flowed-text is +needed for recent versions. + +... the "no-strip-whitespace-before-send" option, too. AFAIK it +was introduced in 4.60. + +(Linus Torvalds) + +And 4.58 needs at least this. + +--- +diff-tree 8326dd8350be64ac7fc805f6563a1d61ad10d32c (from e886a61f76edf5410573e92e38ce22974f9c40f1) +Author: Linus Torvalds +Date: Mon Aug 15 17:23:51 2005 -0700 + + Fix pine whitespace-corruption bug + + There's no excuse for unconditionally removing whitespace from + the pico buffers on close. + +diff --git a/pico/pico.c b/pico/pico.c +--- a/pico/pico.c ++++ b/pico/pico.c +@@ -219,7 +219,9 @@ PICO *pm; + switch(pico_all_done){ /* prepare for/handle final events */ + case COMP_EXIT : /* already confirmed */ + packheader(); ++#if 0 + stripwhitespace(); ++#endif + c |= COMP_EXIT; + break; + + +(Daniel Barkalow) + +> A patch to SubmittingPatches, MUA specific help section for +> users of Pine 4.63 would be very much appreciated. + +Ah, it looks like a recent version changed the default behavior to do the +right thing, and inverted the sense of the configuration option. (Either +that or Gentoo did it.) So you need to set the +"no-strip-whitespace-before-send" option, unless the option you have is +"strip-whitespace-before-send", in which case you should avoid checking +it. + + +Thunderbird +----------- + +(A Large Angry SCM) + +Here are some hints on how to successfully submit patches inline using +Thunderbird. + +This recipe appears to work with the current [*1*] Thunderbird from Suse. + +The following Thunderbird extensions are needed: + AboutConfig 0.5 + http://aboutconfig.mozdev.org/ + External Editor 0.7.2 + http://globs.org/articles.php?lng=en&pg=8 + +1) Prepare the patch as a text file using your method of choice. + +2) Before opening a compose window, use Edit->Account Settings to +uncheck the "Compose messages in HTML format" setting in the +"Composition & Addressing" panel of the account to be used to send the +patch. [*2*] + +3) In the main Thunderbird window, _before_ you open the compose window +for the patch, use Tools->about:config to set the following to the +indicated values: + mailnews.send_plaintext_flowed => false + mailnews.wraplength => 0 + +4) Open a compose window and click the external editor icon. + +5) In the external editor window, read in the patch file and exit the +editor normally. + +6) Back in the compose window: Add whatever other text you wish to the +message, complete the addressing and subject fields, and press send. + +7) Optionally, undo the about:config/account settings changes made in +steps 2 & 3. + + +[Footnotes] +*1* Version 1.0 (20041207) from the MozillaThunderbird-1.0-5 rpm of Suse +9.3 professional updates. + +*2* It may be possible to do this with about:config and the following +settings but I haven't tried, yet. + mail.html_compose => false + mail.identity.default.compose_html => false + mail.identity.id?.compose_html => false + diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf new file mode 100644 index 00000000..7ce71510 --- /dev/null +++ b/Documentation/asciidoc.conf @@ -0,0 +1,36 @@ +## gitlink: macro +# +# Usage: gitlink:command[manpage-section] +# +# Note, {0} is the manpage section, while {target} is the command. +# +# Show GIT link as: (
); if section is defined, else just show +# the command. + +[attributes] +caret=^ + +ifdef::backend-docbook[] +[gitlink-inlinemacro] +{0%{target}} +{0#} +{0#{target}{0}} +{0#} +endif::backend-docbook[] + +ifdef::backend-docbook[] +# "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this. +[listingblock] +{title} + +| + +{title#} +endif::backend-docbook[] + +ifdef::backend-xhtml11[] +[gitlink-inlinemacro] +{target}{0?({0})} +endif::backend-xhtml11[] + + diff --git a/Documentation/build-docdep.perl b/Documentation/build-docdep.perl new file mode 100755 index 00000000..489389c3 --- /dev/null +++ b/Documentation/build-docdep.perl @@ -0,0 +1,50 @@ +#!/usr/bin/perl + +my %include = (); +my %included = (); + +for my $text (<*.txt>) { + open I, '<', $text || die "cannot read: $text"; + while () { + if (/^include::/) { + chomp; + s/^include::\s*//; + s/\[\]//; + $include{$text}{$_} = 1; + $included{$_} = 1; + } + } + close I; +} + +# Do we care about chained includes??? +my $changed = 1; +while ($changed) { + $changed = 0; + while (my ($text, $included) = each %include) { + for my $i (keys %$included) { + # $text has include::$i; if $i includes $j + # $text indirectly includes $j. + if (exists $include{$i}) { + for my $j (keys %{$include{$i}}) { + if (!exists $include{$text}{$j}) { + $include{$text}{$j} = 1; + $included{$j} = 1; + $changed = 1; + } + } + } + } + } +} + +while (my ($text, $included) = each %include) { + if (! exists $included{$text} && + (my $base = $text) =~ s/\.txt$//) { + my ($suffix) = '1'; + if ($base eq 'git') { + $suffix = '7'; # yuck... + } + print "$base.html $base.$suffix : ", join(" ", keys %$included), "\n"; + } +} diff --git a/Documentation/callouts.xsl b/Documentation/callouts.xsl new file mode 100644 index 00000000..ad03755d --- /dev/null +++ b/Documentation/callouts.xsl @@ -0,0 +1,16 @@ + + + + + + + .sp + + + + + + + .br + + diff --git a/Documentation/config.txt b/Documentation/config.txt new file mode 100644 index 00000000..a04c5adf --- /dev/null +++ b/Documentation/config.txt @@ -0,0 +1,200 @@ +CONFIGURATION FILE +------------------ + +The git configuration file contains a number of variables that affect +the git command's behavior. They can be used by both the git plumbing +and the porcelains. The variables are divided into sections, where +in the fully qualified variable name the variable itself is the last +dot-separated segment and the section name is everything before the last +dot. The variable names are case-insensitive and only alphanumeric +characters are allowed. Some variables may appear multiple times. + +The syntax is fairly flexible and permissive; whitespaces are mostly +ignored. The '#' and ';' characters begin comments to the end of line, +blank lines are ignored, lines containing strings enclosed in square +brackets start sections and 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". String values may be entirely or partially +enclosed in double quotes; some variables may require special value format. + +Example +~~~~~~~ + + # Core variables + [core] + ; Don't trust file modes + filemode = false + + # Our diff algorithm + [diff] + external = "/usr/local/bin/gnu-diff -u" + renames = true + +Variables +~~~~~~~~~ + +Note that this list is non-comprehensive and not necessarily complete. +For command-specific variables, you will find a more detailed description +in the appropriate manual page. You will find a description of non-core +porcelain configuration variables in the respective porcelain documentation. + +core.fileMode:: + If false, the executable bit differences between the index and + the working copy are ignored; useful on broken filesystems like FAT. + See gitlink:git-update-index[1]. True by default. + +core.gitProxy:: + A "proxy command" to execute (as 'command host port') instead + of establishing direct connection to the remote server when + using the git protocol for fetching. If the variable value is + in the "COMMAND for DOMAIN" format, the command is applied only + on hostnames ending with the specified domain string. This variable + may be set multiple times and is matched in the given order; + the first match wins. ++ +Can be overridden by the 'GIT_PROXY_COMMAND' environment variable +(which always applies universally, without the special "for" +handling). + +core.ignoreStat:: + The working copy files are assumed to stay unchanged until you + mark them otherwise manually - Git will not detect the file changes + by lstat() calls. This is useful on systems where those are very + slow, such as Microsoft Windows. See gitlink:git-update-index[1]. + False by default. + +core.preferSymlinkRefs:: + Instead of the default "symref" format for HEAD + and other symbolic reference files, use symbolic links. + This is sometimes needed to work with old scripts that + expect HEAD to be a symbolic link. + +core.logAllRefUpdates:: + If true, `git-update-ref` will append a line to + "$GIT_DIR/logs/" listing the new SHA1 and the date/time + of the update. If the file does not exist it will be + created automatically. This information can be used to + determine what commit was the tip of a branch "2 days ago". + This value is false by default (no logging). + +core.repositoryFormatVersion:: + Internal variable identifying the repository format and layout + version. + +core.sharedRepository:: + If true, the repository is made shareable between several users + in a group (making sure all the files and objects are group-writable). + See gitlink:git-init-db[1]. False by default. + +core.warnAmbiguousRefs:: + If true, git will warn you if the ref name you passed it is ambiguous + and might match multiple refs in the .git/refs/ tree. True by default. + +alias.*:: + Command aliases for the gitlink:git[1] command wrapper - e.g. + after defining "alias.last = cat-file commit HEAD", the invocation + "git last" is equivalent to "git cat-file commit HEAD". To avoid + confusion and troubles with script usage, aliases that + hide existing git commands are ignored. Arguments are split by + spaces, the usual shell quoting and escaping is supported. + quote pair and a backslash can be used to quote them. + +apply.whitespace:: + Tells `git-apply` how to handle whitespaces, in the same way + as the '--whitespace' option. See gitlink:git-apply[1]. + +diff.renameLimit:: + The number of files to consider when performing the copy/rename + detection; equivalent to the git diff option '-l'. + +format.headers:: + Additional email headers to include in a patch to be submitted + by mail. See gitlink:git-format-patch[1]. + +gitcvs.enabled:: + Whether the cvs pserver interface is enabled for this repository. + See gitlink:git-cvsserver[1]. + +gitcvs.logfile:: + Path to a log file where the cvs pserver interface well... logs + various stuff. See gitlink:git-cvsserver[1]. + +http.sslVerify:: + Whether to verify the SSL certificate when fetching or pushing + over HTTPS. Can be overridden by the 'GIT_SSL_NO_VERIFY' environment + variable. + +http.sslCert:: + File containing the SSL certificate when fetching or pushing + over HTTPS. Can be overridden by the 'GIT_SSL_CERT' environment + variable. + +http.sslKey:: + File containing the SSL private key when fetching or pushing + over HTTPS. Can be overridden by the 'GIT_SSL_KEY' environment + variable. + +http.sslCAInfo:: + File containing the certificates to verify the peer with when + fetching or pushing over HTTPS. Can be overridden by the + 'GIT_SSL_CAINFO' environment variable. + +http.sslCAPath:: + Path containing files with the CA certificates to verify the peer + with when fetching or pushing over HTTPS. Can be overridden + by the 'GIT_SSL_CAPATH' environment variable. + +http.maxRequests:: + How many HTTP requests to launch in parallel. Can be overridden + by the 'GIT_HTTP_MAX_REQUESTS' environment variable. Default is 5. + +http.lowSpeedLimit, http.lowSpeedTime:: + If the HTTP transfer speed is less than 'http.lowSpeedLimit' + for longer than 'http.lowSpeedTime' seconds, the transfer is aborted. + Can be overridden by the 'GIT_HTTP_LOW_SPEED_LIMIT' and + 'GIT_HTTP_LOW_SPEED_TIME' environment variables. + +i18n.commitEncoding:: + Character encoding the commit messages are stored in; git itself + does not care per se, but this information is necessary e.g. when + importing commits from emails or in the gitk graphical history + browser (and possibly at other places in the future or in other + porcelains). See e.g. gitlink:git-mailinfo[1]. Defaults to 'utf-8'. + +merge.summary:: + Whether to include summaries of merged commits in newly created + merge commit messages. False by default. + +pull.octopus:: + The default merge strategy to use when pulling multiple branches + at once. + +pull.twohead:: + The default merge strategy to use when pulling a single branch. + +show.difftree:: + The default gitlink:git-diff-tree[1] arguments to be used + for gitlink:git-show[1]. + +showbranch.default:: + The default set of branches for gitlink:git-show-branch[1]. + See gitlink:git-show-branch[1]. + +user.email:: + Your email address to be recorded in any newly created commits. + Can be overridden by the 'GIT_AUTHOR_EMAIL' and 'GIT_COMMITTER_EMAIL' + environment variables. See gitlink:git-commit-tree[1]. + +user.name:: + Your full name to be recorded in any newly created commits. + Can be overridden by the 'GIT_AUTHOR_NAME' and 'GIT_COMMITTER_NAME' + environment variables. See gitlink:git-commit-tree[1]. + +whatchanged.difftree:: + The default gitlink:git-diff-tree[1] arguments to be used + for gitlink:git-whatchanged[1]. + +imap:: + The configuration variables in the 'imap' section are described + in gitlink:git-imap-send[1]. diff --git a/Documentation/core-tutorial.txt b/Documentation/core-tutorial.txt new file mode 100644 index 00000000..1185897f --- /dev/null +++ b/Documentation/core-tutorial.txt @@ -0,0 +1,1722 @@ +A git core tutorial for developers +================================== + +Introduction +------------ + +This is trying to be a short tutorial on setting up and using a git +repository, mainly because being hands-on and using explicit examples is +often the best way of explaining what is going on. + +In normal life, most people wouldn't use the "core" git programs +directly, but rather script around them to make them more palatable. +Understanding the core git stuff may help some people get those scripts +done, though, and it may also be instructive in helping people +understand what it is that the higher-level helper scripts are actually +doing. + +The core git is often called "plumbing", with the prettier user +interfaces on top of it called "porcelain". You may not want to use the +plumbing directly very often, but it can be good to know what the +plumbing does for when the porcelain isn't flushing. + +The material presented here often goes deep describing how things +work internally. If you are mostly interested in using git as a +SCM, you can skip them during your first pass. + +[NOTE] +And those "too deep" descriptions are often marked as Note. + +[NOTE] +If you are already familiar with another version control system, +like CVS, you may want to take a look at +link:everyday.html[Everyday GIT in 20 commands or so] first +before reading this. + + +Creating a git repository +------------------------- + +Creating a new git repository couldn't be easier: all git repositories start +out empty, and the only thing you need to do is find yourself a +subdirectory that you want to use as a working tree - either an empty +one for a totally new project, or an existing working tree that you want +to import into git. + +For our first example, we're going to start a totally new repository from +scratch, with no pre-existing files, and we'll call it `git-tutorial`. +To start up, create a subdirectory for it, change into that +subdirectory, and initialize the git infrastructure with `git-init-db`: + +------------------------------------------------ +$ mkdir git-tutorial +$ cd git-tutorial +$ git-init-db +------------------------------------------------ + +to which git will reply + +---------------- +defaulting to local storage area +---------------- + +which is just git's way of saying that you haven't been doing anything +strange, and that it will have created a local `.git` directory setup for +your new project. You will now have a `.git` directory, and you can +inspect that with `ls`. For your new empty project, it should show you +three entries, among other things: + + - a file called `HEAD`, that has `ref: refs/heads/master` in it. + This is similar to a symbolic link and points at + `refs/heads/master` relative to the `HEAD` file. ++ +Don't worry about the fact that the file that the `HEAD` link points to +doesn't even exist yet -- you haven't created the commit that will +start your `HEAD` development branch yet. + + - a subdirectory called `objects`, which will contain all the + objects of your project. You should never have any real reason to + look at the objects directly, but you might want to know that these + objects are what contains all the real 'data' in your repository. + + - a subdirectory called `refs`, which contains references to objects. + +In particular, the `refs` subdirectory will contain two other +subdirectories, named `heads` and `tags` respectively. They do +exactly what their names imply: they contain references to any number +of different 'heads' of development (aka 'branches'), and to any +'tags' that you have created to name specific versions in your +repository. + +One note: the special `master` head is the default branch, which is +why the `.git/HEAD` file was created points to it even if it +doesn't yet exist. Basically, the `HEAD` link is supposed to always +point to the branch you are working on right now, and you always +start out expecting to work on the `master` branch. + +However, this is only a convention, and you can name your branches +anything you want, and don't have to ever even 'have' a `master` +branch. A number of the git tools will assume that `.git/HEAD` is +valid, though. + +[NOTE] +An 'object' is identified by its 160-bit SHA1 hash, aka 'object name', +and a reference to an object is always the 40-byte hex +representation of that SHA1 name. The files in the `refs` +subdirectory are expected to contain these hex references +(usually with a final `\'\n\'` at the end), and you should thus +expect to see a number of 41-byte files containing these +references in these `refs` subdirectories when you actually start +populating your tree. + +[NOTE] +An advanced user may want to take a look at the +link:repository-layout.html[repository layout] document +after finishing this tutorial. + +You have now created your first git repository. Of course, since it's +empty, that's not very useful, so let's start populating it with data. + + +Populating a git repository +--------------------------- + +We'll keep this simple and stupid, so we'll start off with populating a +few trivial files just to get a feel for it. + +Start off with just creating any random files that you want to maintain +in your git repository. We'll start off with a few bad examples, just to +get a feel for how this works: + +------------------------------------------------ +$ echo "Hello World" >hello +$ echo "Silly example" >example +------------------------------------------------ + +you have now created two files in your working tree (aka 'working directory'), +but to actually check in your hard work, you will have to go through two steps: + + - fill in the 'index' file (aka 'cache') with the information about your + working tree state. + + - commit that index file as an object. + +The first step is trivial: when you want to tell git about any changes +to your working tree, you use the `git-update-index` program. That +program normally just takes a list of filenames you want to update, but +to avoid trivial mistakes, it refuses to add new entries to the index +(or remove existing ones) unless you explicitly tell it that you're +adding a new entry with the `\--add` flag (or removing an entry with the +`\--remove`) flag. + +So to populate the index with the two files you just created, you can do + +------------------------------------------------ +$ git-update-index --add hello example +------------------------------------------------ + +and you have now told git to track those two files. + +In fact, as you did that, if you now look into your object directory, +you'll notice that git will have added two new objects to the object +database. If you did exactly the steps above, you should now be able to do + + +---------------- +$ ls .git/objects/??/* +---------------- + +and see two files: + +---------------- +.git/objects/55/7db03de997c86a4a028e1ebd3a1ceb225be238 +.git/objects/f2/4c74a2e500f5ee1332c86b94199f52b1d1d962 +---------------- + +which correspond with the objects with names of `557db...` and +`f24c7...` respectively. + +If you want to, you can use `git-cat-file` to look at those objects, but +you'll have to use the object name, not the filename of the object: + +---------------- +$ git-cat-file -t 557db03de997c86a4a028e1ebd3a1ceb225be238 +---------------- + +where the `-t` tells `git-cat-file` to tell you what the "type" of the +object is. git will tell you that you have a "blob" object (i.e., just a +regular file), and you can see the contents with + +---------------- +$ git-cat-file "blob" 557db03 +---------------- + +which will print out "Hello World". The object `557db03` is nothing +more than the contents of your file `hello`. + +[NOTE] +Don't confuse that object with the file `hello` itself. The +object is literally just those specific *contents* of the file, and +however much you later change the contents in file `hello`, the object +we just looked at will never change. Objects are immutable. + +[NOTE] +The second example demonstrates that you can +abbreviate the object name to only the first several +hexadecimal digits in most places. + +Anyway, as we mentioned previously, you normally never actually take a +look at the objects themselves, and typing long 40-character hex +names is not something you'd normally want to do. The above digression +was just to show that `git-update-index` did something magical, and +actually saved away the contents of your files into the git object +database. + +Updating the index did something else too: it created a `.git/index` +file. This is the index that describes your current working tree, and +something you should be very aware of. Again, you normally never worry +about the index file itself, but you should be aware of the fact that +you have not actually really "checked in" your files into git so far, +you've only *told* git about them. + +However, since git knows about them, you can now start using some of the +most basic git commands to manipulate the files or look at their status. + +In particular, let's not even check in the two files into git yet, we'll +start off by adding another line to `hello` first: + +------------------------------------------------ +$ echo "It's a new day for git" >>hello +------------------------------------------------ + +and you can now, since you told git about the previous state of `hello`, ask +git what has changed in the tree compared to your old index, using the +`git-diff-files` command: + +------------ +$ git-diff-files +------------ + +Oops. That wasn't very readable. It just spit out its own internal +version of a `diff`, but that internal version really just tells you +that it has noticed that "hello" has been modified, and that the old object +contents it had have been replaced with something else. + +To make it readable, we can tell git-diff-files to output the +differences as a patch, using the `-p` flag: + +------------ +$ git-diff-files -p +diff --git a/hello b/hello +index 557db03..263414f 100644 +--- a/hello ++++ b/hello +@@ -1 +1,2 @@ + Hello World ++It's a new day for git +---- + +i.e. the diff of the change we caused by adding another line to `hello`. + +In other words, `git-diff-files` always shows us the difference between +what is recorded in the index, and what is currently in the working +tree. That's very useful. + +A common shorthand for `git-diff-files -p` is to just write `git +diff`, which will do the same thing. + +------------ +$ git diff +diff --git a/hello b/hello +index 557db03..263414f 100644 +--- a/hello ++++ b/hello +@@ -1 +1,2 @@ + Hello World ++It's a new day for git +------------ + + +Committing git state +-------------------- + +Now, we want to go to the next stage in git, which is to take the files +that git knows about in the index, and commit them as a real tree. We do +that in two phases: creating a 'tree' object, and committing that 'tree' +object as a 'commit' object together with an explanation of what the +tree was all about, along with information of how we came to that state. + +Creating a tree object is trivial, and is done with `git-write-tree`. +There are no options or other input: git-write-tree will take the +current index state, and write an object that describes that whole +index. In other words, we're now tying together all the different +filenames with their contents (and their permissions), and we're +creating the equivalent of a git "directory" object: + +------------------------------------------------ +$ git-write-tree +------------------------------------------------ + +and this will just output the name of the resulting tree, in this case +(if you have done exactly as I've described) it should be + +---------------- +8988da15d077d4829fc51d8544c097def6644dbb +---------------- + +which is another incomprehensible object name. Again, if you want to, +you can use `git-cat-file -t 8988d\...` to see that this time the object +is not a "blob" object, but a "tree" object (you can also use +`git-cat-file` to actually output the raw object contents, but you'll see +mainly a binary mess, so that's less interesting). + +However -- normally you'd never use `git-write-tree` on its own, because +normally you always commit a tree into a commit object using the +`git-commit-tree` command. In fact, it's easier to not actually use +`git-write-tree` on its own at all, but to just pass its result in as an +argument to `git-commit-tree`. + +`git-commit-tree` normally takes several arguments -- it wants to know +what the 'parent' of a commit was, but since this is the first commit +ever in this new repository, and it has no parents, we only need to pass in +the object name of the tree. However, `git-commit-tree` +also wants to get a commit message +on its standard input, and it will write out the resulting object name for the +commit to its standard output. + +And this is where we create the `.git/refs/heads/master` file +which is pointed at by `HEAD`. This file is supposed to contain +the reference to the top-of-tree of the master branch, and since +that's exactly what `git-commit-tree` spits out, we can do this +all with a sequence of simple shell commands: + +------------------------------------------------ +$ tree=$(git-write-tree) +$ commit=$(echo 'Initial commit' | git-commit-tree $tree) +$ git-update-ref HEAD $commit +------------------------------------------------ + +which will say: + +---------------- +Committing initial tree 8988da15d077d4829fc51d8544c097def6644dbb +---------------- + +just to warn you about the fact that it created a totally new commit +that is not related to anything else. Normally you do this only *once* +for a project ever, and all later commits will be parented on top of an +earlier commit, and you'll never see this "Committing initial tree" +message ever again. + +Again, normally you'd never actually do this by hand. There is a +helpful script called `git commit` that will do all of this for you. So +you could have just written `git commit` +instead, and it would have done the above magic scripting for you. + + +Making a change +--------------- + +Remember how we did the `git-update-index` on file `hello` and then we +changed `hello` afterward, and could compare the new state of `hello` with the +state we saved in the index file? + +Further, remember how I said that `git-write-tree` writes the contents +of the *index* file to the tree, and thus what we just committed was in +fact the *original* contents of the file `hello`, not the new ones. We did +that on purpose, to show the difference between the index state, and the +state in the working tree, and how they don't have to match, even +when we commit things. + +As before, if we do `git-diff-files -p` in our git-tutorial project, +we'll still see the same difference we saw last time: the index file +hasn't changed by the act of committing anything. However, now that we +have committed something, we can also learn to use a new command: +`git-diff-index`. + +Unlike `git-diff-files`, which showed the difference between the index +file and the working tree, `git-diff-index` shows the differences +between a committed *tree* and either the index file or the working +tree. In other words, `git-diff-index` wants a tree to be diffed +against, and before we did the commit, we couldn't do that, because we +didn't have anything to diff against. + +But now we can do + +---------------- +$ git-diff-index -p HEAD +---------------- + +(where `-p` has the same meaning as it did in `git-diff-files`), and it +will show us the same difference, but for a totally different reason. +Now we're comparing the working tree not against the index file, +but against the tree we just wrote. It just so happens that those two +are obviously the same, so we get the same result. + +Again, because this is a common operation, you can also just shorthand +it with + +---------------- +$ git diff HEAD +---------------- + +which ends up doing the above for you. + +In other words, `git-diff-index` normally compares a tree against the +working tree, but when given the `\--cached` flag, it is told to +instead compare against just the index cache contents, and ignore the +current working tree state entirely. Since we just wrote the index +file to HEAD, doing `git-diff-index \--cached -p HEAD` should thus return +an empty set of differences, and that's exactly what it does. + +[NOTE] +================ +`git-diff-index` really always uses the index for its +comparisons, and saying that it compares a tree against the working +tree is thus not strictly accurate. In particular, the list of +files to compare (the "meta-data") *always* comes from the index file, +regardless of whether the `\--cached` flag is used or not. The `\--cached` +flag really only determines whether the file *contents* to be compared +come from the working tree or not. + +This is not hard to understand, as soon as you realize that git simply +never knows (or cares) about files that it is not told about +explicitly. git will never go *looking* for files to compare, it +expects you to tell it what the files are, and that's what the index +is there for. +================ + +However, our next step is to commit the *change* we did, and again, to +understand what's going on, keep in mind the difference between "working +tree contents", "index file" and "committed tree". We have changes +in the working tree that we want to commit, and we always have to +work through the index file, so the first thing we need to do is to +update the index cache: + +------------------------------------------------ +$ git-update-index hello +------------------------------------------------ + +(note how we didn't need the `\--add` flag this time, since git knew +about the file already). + +Note what happens to the different `git-diff-\*` versions here. After +we've updated `hello` in the index, `git-diff-files -p` now shows no +differences, but `git-diff-index -p HEAD` still *does* show that the +current state is different from the state we committed. In fact, now +`git-diff-index` shows the same difference whether we use the `--cached` +flag or not, since now the index is coherent with the working tree. + +Now, since we've updated `hello` in the index, we can commit the new +version. We could do it by writing the tree by hand again, and +committing the tree (this time we'd have to use the `-p HEAD` flag to +tell commit that the HEAD was the *parent* of the new commit, and that +this wasn't an initial commit any more), but you've done that once +already, so let's just use the helpful script this time: + +------------------------------------------------ +$ git commit +------------------------------------------------ + +which starts an editor for you to write the commit message and tells you +a bit about what you have done. + +Write whatever message you want, and all the lines that start with '#' +will be pruned out, and the rest will be used as the commit message for +the change. If you decide you don't want to commit anything after all at +this point (you can continue to edit things and update the index), you +can just leave an empty message. Otherwise `git commit` will commit +the change for you. + +You've now made your first real git commit. And if you're interested in +looking at what `git commit` really does, feel free to investigate: +it's a few very simple shell scripts to generate the helpful (?) commit +message headers, and a few one-liners that actually do the +commit itself (`git-commit`). + + +Inspecting Changes +------------------ + +While creating changes is useful, it's even more useful if you can tell +later what changed. The most useful command for this is another of the +`diff` family, namely `git-diff-tree`. + +`git-diff-tree` can be given two arbitrary trees, and it will tell you the +differences between them. Perhaps even more commonly, though, you can +give it just a single commit object, and it will figure out the parent +of that commit itself, and show the difference directly. Thus, to get +the same diff that we've already seen several times, we can now do + +---------------- +$ git-diff-tree -p HEAD +---------------- + +(again, `-p` means to show the difference as a human-readable patch), +and it will show what the last commit (in `HEAD`) actually changed. + +[NOTE] +============ +Here is an ASCII art by Jon Loeliger that illustrates how +various diff-\* commands compare things. + + diff-tree + +----+ + | | + | | + V V + +-----------+ + | Object DB | + | Backing | + | Store | + +-----------+ + ^ ^ + | | + | | diff-index --cached + | | + diff-index | V + | +-----------+ + | | Index | + | | "cache" | + | +-----------+ + | ^ + | | + | | diff-files + | | + V V + +-----------+ + | Working | + | Directory | + +-----------+ +============ + +More interestingly, you can also give `git-diff-tree` the `--pretty` flag, +which tells it to also show the commit message and author and date of the +commit, and you can tell it to show a whole series of diffs. +Alternatively, you can tell it to be "silent", and not show the diffs at +all, but just show the actual commit message. + +In fact, together with the `git-rev-list` program (which generates a +list of revisions), `git-diff-tree` ends up being a veritable fount of +changes. A trivial (but very useful) script called `git-whatchanged` is +included with git which does exactly this, and shows a log of recent +activities. + +To see the whole history of our pitiful little git-tutorial project, you +can do + +---------------- +$ git log +---------------- + +which shows just the log messages, or if we want to see the log together +with the associated patches use the more complex (and much more +powerful) + +---------------- +$ git-whatchanged -p --root +---------------- + +and you will see exactly what has changed in the repository over its +short history. + +[NOTE] +The `\--root` flag is a flag to `git-diff-tree` to tell it to +show the initial aka 'root' commit too. Normally you'd probably not +want to see the initial import diff, but since the tutorial project +was started from scratch and is so small, we use it to make the result +a bit more interesting. + +With that, you should now be having some inkling of what git does, and +can explore on your own. + +[NOTE] +Most likely, you are not directly using the core +git Plumbing commands, but using Porcelain like Cogito on top +of it. Cogito works a bit differently and you usually do not +have to run `git-update-index` yourself for changed files (you +do tell underlying git about additions and removals via +`cg-add` and `cg-rm` commands). Just before you make a commit +with `cg-commit`, Cogito figures out which files you modified, +and runs `git-update-index` on them for you. + + +Tagging a version +----------------- + +In git, there are two kinds of tags, a "light" one, and an "annotated tag". + +A "light" tag is technically nothing more than a branch, except we put +it in the `.git/refs/tags/` subdirectory instead of calling it a `head`. +So the simplest form of tag involves nothing more than + +------------------------------------------------ +$ git tag my-first-tag +------------------------------------------------ + +which just writes the current `HEAD` into the `.git/refs/tags/my-first-tag` +file, after which point you can then use this symbolic name for that +particular state. You can, for example, do + +---------------- +$ git diff my-first-tag +---------------- + +to diff your current state against that tag (which at this point will +obviously be an empty diff, but if you continue to develop and commit +stuff, you can use your tag as an "anchor-point" to see what has changed +since you tagged it. + +An "annotated tag" is actually a real git object, and contains not only a +pointer to the state you want to tag, but also a small tag name and +message, along with optionally a PGP signature that says that yes, +you really did +that tag. You create these annotated tags with either the `-a` or +`-s` flag to `git tag`: + +---------------- +$ git tag -s +---------------- + +which will sign the current `HEAD` (but you can also give it another +argument that specifies the thing to tag, i.e., you could have tagged the +current `mybranch` point by using `git tag mybranch`). + +You normally only do signed tags for major releases or things +like that, while the light-weight tags are useful for any marking you +want to do -- any time you decide that you want to remember a certain +point, just create a private tag for it, and you have a nice symbolic +name for the state at that point. + + +Copying repositories +-------------------- + +git repositories are normally totally self-sufficient and relocatable +Unlike CVS, for example, there is no separate notion of +"repository" and "working tree". A git repository normally *is* the +working tree, with the local git information hidden in the `.git` +subdirectory. There is nothing else. What you see is what you got. + +[NOTE] +You can tell git to split the git internal information from +the directory that it tracks, but we'll ignore that for now: it's not +how normal projects work, and it's really only meant for special uses. +So the mental model of "the git information is always tied directly to +the working tree that it describes" may not be technically 100% +accurate, but it's a good model for all normal use. + +This has two implications: + + - if you grow bored with the tutorial repository you created (or you've + made a mistake and want to start all over), you can just do simple ++ +---------------- +$ rm -rf git-tutorial +---------------- ++ +and it will be gone. There's no external repository, and there's no +history outside the project you created. + + - if you want to move or duplicate a git repository, you can do so. There + is `git clone` command, but if all you want to do is just to + create a copy of your repository (with all the full history that + went along with it), you can do so with a regular + `cp -a git-tutorial new-git-tutorial`. ++ +Note that when you've moved or copied a git repository, your git index +file (which caches various information, notably some of the "stat" +information for the files involved) will likely need to be refreshed. +So after you do a `cp -a` to create a new copy, you'll want to do ++ +---------------- +$ git-update-index --refresh +---------------- ++ +in the new repository to make sure that the index file is up-to-date. + +Note that the second point is true even across machines. You can +duplicate a remote git repository with *any* regular copy mechanism, be it +`scp`, `rsync` or `wget`. + +When copying a remote repository, you'll want to at a minimum update the +index cache when you do this, and especially with other peoples' +repositories you often want to make sure that the index cache is in some +known state (you don't know *what* they've done and not yet checked in), +so usually you'll precede the `git-update-index` with a + +---------------- +$ git-read-tree --reset HEAD +$ git-update-index --refresh +---------------- + +which will force a total index re-build from the tree pointed to by `HEAD`. +It resets the index contents to `HEAD`, and then the `git-update-index` +makes sure to match up all index entries with the checked-out files. +If the original repository had uncommitted changes in its +working tree, `git-update-index --refresh` notices them and +tells you they need to be updated. + +The above can also be written as simply + +---------------- +$ git reset +---------------- + +and in fact a lot of the common git command combinations can be scripted +with the `git xyz` interfaces. You can learn things by just looking +at what the various git scripts do. For example, `git reset` is the +above two lines implemented in `git-reset`, but some things like +`git status` and `git commit` are slightly more complex scripts around +the basic git commands. + +Many (most?) public remote repositories will not contain any of +the checked out files or even an index file, and will *only* contain the +actual core git files. Such a repository usually doesn't even have the +`.git` subdirectory, but has all the git files directly in the +repository. + +To create your own local live copy of such a "raw" git repository, you'd +first create your own subdirectory for the project, and then copy the +raw repository contents into the `.git` directory. For example, to +create your own copy of the git repository, you'd do the following + +---------------- +$ mkdir my-git +$ cd my-git +$ rsync -rL rsync://rsync.kernel.org/pub/scm/git/git.git/ .git +---------------- + +followed by + +---------------- +$ git-read-tree HEAD +---------------- + +to populate the index. However, now you have populated the index, and +you have all the git internal files, but you will notice that you don't +actually have any of the working tree files to work on. To get +those, you'd check them out with + +---------------- +$ git-checkout-index -u -a +---------------- + +where the `-u` flag means that you want the checkout to keep the index +up-to-date (so that you don't have to refresh it afterward), and the +`-a` flag means "check out all files" (if you have a stale copy or an +older version of a checked out tree you may also need to add the `-f` +flag first, to tell git-checkout-index to *force* overwriting of any old +files). + +Again, this can all be simplified with + +---------------- +$ git clone rsync://rsync.kernel.org/pub/scm/git/git.git/ my-git +$ cd my-git +$ git checkout +---------------- + +which will end up doing all of the above for you. + +You have now successfully copied somebody else's (mine) remote +repository, and checked it out. + + +Creating a new branch +--------------------- + +Branches in git are really nothing more than pointers into the git +object database from within the `.git/refs/` subdirectory, and as we +already discussed, the `HEAD` branch is nothing but a symlink to one of +these object pointers. + +You can at any time create a new branch by just picking an arbitrary +point in the project history, and just writing the SHA1 name of that +object into a file under `.git/refs/heads/`. You can use any filename you +want (and indeed, subdirectories), but the convention is that the +"normal" branch is called `master`. That's just a convention, though, +and nothing enforces it. + +To show that as an example, let's go back to the git-tutorial repository we +used earlier, and create a branch in it. You do that by simply just +saying that you want to check out a new branch: + +------------ +$ git checkout -b mybranch +------------ + +will create a new branch based at the current `HEAD` position, and switch +to it. + +[NOTE] +================================================ +If you make the decision to start your new branch at some +other point in the history than the current `HEAD`, you can do so by +just telling `git checkout` what the base of the checkout would be. +In other words, if you have an earlier tag or branch, you'd just do + +------------ +$ git checkout -b mybranch earlier-commit +------------ + +and it would create the new branch `mybranch` at the earlier commit, +and check out the state at that time. +================================================ + +You can always just jump back to your original `master` branch by doing + +------------ +$ git checkout master +------------ + +(or any other branch-name, for that matter) and if you forget which +branch you happen to be on, a simple + +------------ +$ cat .git/HEAD +------------ + +will tell you where it's pointing. To get the list of branches +you have, you can say + +------------ +$ git branch +------------ + +which is nothing more than a simple script around `ls .git/refs/heads`. +There will be asterisk in front of the branch you are currently on. + +Sometimes you may wish to create a new branch _without_ actually +checking it out and switching to it. If so, just use the command + +------------ +$ git branch [startingpoint] +------------ + +which will simply _create_ the branch, but will not do anything further. +You can then later -- once you decide that you want to actually develop +on that branch -- switch to that branch with a regular `git checkout` +with the branchname as the argument. + + +Merging two branches +-------------------- + +One of the ideas of having a branch is that you do some (possibly +experimental) work in it, and eventually merge it back to the main +branch. So assuming you created the above `mybranch` that started out +being the same as the original `master` branch, let's make sure we're in +that branch, and do some work there. + +------------------------------------------------ +$ git checkout mybranch +$ echo "Work, work, work" >>hello +$ git commit -m 'Some work.' -i hello +------------------------------------------------ + +Here, we just added another line to `hello`, and we used a shorthand for +doing both `git-update-index hello` and `git commit` by just giving the +filename directly to `git commit`, with an `-i` flag (it tells +git to 'include' that file in addition to what you have done to +the index file so far when making the commit). The `-m` flag is to give the +commit log message from the command line. + +Now, to make it a bit more interesting, let's assume that somebody else +does some work in the original branch, and simulate that by going back +to the master branch, and editing the same file differently there: + +------------ +$ git checkout master +------------ + +Here, take a moment to look at the contents of `hello`, and notice how they +don't contain the work we just did in `mybranch` -- because that work +hasn't happened in the `master` branch at all. Then do + +------------ +$ echo "Play, play, play" >>hello +$ echo "Lots of fun" >>example +$ git commit -m 'Some fun.' -i hello example +------------ + +since the master branch is obviously in a much better mood. + +Now, you've got two branches, and you decide that you want to merge the +work done. Before we do that, let's introduce a cool graphical tool that +helps you view what's going on: + +---------------- +$ gitk --all +---------------- + +will show you graphically both of your branches (that's what the `\--all` +means: normally it will just show you your current `HEAD`) and their +histories. You can also see exactly how they came to be from a common +source. + +Anyway, let's exit `gitk` (`^Q` or the File menu), and decide that we want +to merge the work we did on the `mybranch` branch into the `master` +branch (which is currently our `HEAD` too). To do that, there's a nice +script called `git merge`, which wants to know which branches you want +to resolve and what the merge is all about: + +------------ +$ git merge "Merge work in mybranch" HEAD mybranch +------------ + +where the first argument is going to be used as the commit message if +the merge can be resolved automatically. + +Now, in this case we've intentionally created a situation where the +merge will need to be fixed up by hand, though, so git will do as much +of it as it can automatically (which in this case is just merge the `example` +file, which had no differences in the `mybranch` branch), and say: + +---------------- + Trying really trivial in-index merge... + fatal: Merge requires file-level merging + Nope. + ... + Auto-merging hello + CONFLICT (content): Merge conflict in hello + Automatic merge failed; fix up by hand +---------------- + +which is way too verbose, but it basically tells you that it failed the +really trivial merge ("Simple merge") and did an "Automatic merge" +instead, but that too failed due to conflicts in `hello`. + +Not to worry. It left the (trivial) conflict in `hello` in the same form you +should already be well used to if you've ever used CVS, so let's just +open `hello` in our editor (whatever that may be), and fix it up somehow. +I'd suggest just making it so that `hello` contains all four lines: + +------------ +Hello World +It's a new day for git +Play, play, play +Work, work, work +------------ + +and once you're happy with your manual merge, just do a + +------------ +$ git commit -i hello +------------ + +which will very loudly warn you that you're now committing a merge +(which is correct, so never mind), and you can write a small merge +message about your adventures in git-merge-land. + +After you're done, start up `gitk \--all` to see graphically what the +history looks like. Notice that `mybranch` still exists, and you can +switch to it, and continue to work with it if you want to. The +`mybranch` branch will not contain the merge, but next time you merge it +from the `master` branch, git will know how you merged it, so you'll not +have to do _that_ merge again. + +Another useful tool, especially if you do not always work in X-Window +environment, is `git show-branch`. + +------------------------------------------------ +$ git show-branch --topo-order master mybranch +* [master] Merge work in mybranch + ! [mybranch] Some work. +-- +- [master] Merge work in mybranch +*+ [mybranch] Some work. +------------------------------------------------ + +The first two lines indicate that it is showing the two branches +and the first line of the commit log message from their +top-of-the-tree commits, you are currently on `master` branch +(notice the asterisk `\*` character), and the first column for +the later output lines is used to show commits contained in the +`master` branch, and the second column for the `mybranch` +branch. Three commits are shown along with their log messages. +All of them have non blank characters in the first column (`*` +shows an ordinary commit on the current branch, `.` is a merge commit), which +means they are now part of the `master` branch. Only the "Some +work" commit has the plus `+` character in the second column, +because `mybranch` has not been merged to incorporate these +commits from the master branch. The string inside brackets +before the commit log message is a short name you can use to +name the commit. In the above example, 'master' and 'mybranch' +are branch heads. 'master~1' is the first parent of 'master' +branch head. Please see 'git-rev-parse' documentation if you +see more complex cases. + +Now, let's pretend you are the one who did all the work in +`mybranch`, and the fruit of your hard work has finally been merged +to the `master` branch. Let's go back to `mybranch`, and run +resolve to get the "upstream changes" back to your branch. + +------------ +$ git checkout mybranch +$ git merge "Merge upstream changes." HEAD master +------------ + +This outputs something like this (the actual commit object names +would be different) + +---------------- +Updating from ae3a2da... to a80b4aa.... +Fast forward + example | 1 + + hello | 1 + + 2 files changed, 2 insertions(+), 0 deletions(-) +---------------- + +Because your branch did not contain anything more than what are +already merged into the `master` branch, the resolve operation did +not actually do a merge. Instead, it just updated the top of +the tree of your branch to that of the `master` branch. This is +often called 'fast forward' merge. + +You can run `gitk \--all` again to see how the commit ancestry +looks like, or run `show-branch`, which tells you this. + +------------------------------------------------ +$ git show-branch master mybranch +! [master] Merge work in mybranch + * [mybranch] Merge work in mybranch +-- +-- [master] Merge work in mybranch +------------------------------------------------ + + +Merging external work +--------------------- + +It's usually much more common that you merge with somebody else than +merging with your own branches, so it's worth pointing out that git +makes that very easy too, and in fact, it's not that different from +doing a `git merge`. In fact, a remote merge ends up being nothing +more than "fetch the work from a remote repository into a temporary tag" +followed by a `git merge`. + +Fetching from a remote repository is done by, unsurprisingly, +`git fetch`: + +---------------- +$ git fetch +---------------- + +One of the following transports can be used to name the +repository to download from: + +Rsync:: + `rsync://remote.machine/path/to/repo.git/` ++ +Rsync transport is usable for both uploading and downloading, +but is completely unaware of what git does, and can produce +unexpected results when you download from the public repository +while the repository owner is uploading into it via `rsync` +transport. Most notably, it could update the files under +`refs/` which holds the object name of the topmost commits +before uploading the files in `objects/` -- the downloader would +obtain head commit object name while that object itself is still +not available in the repository. For this reason, it is +considered deprecated. + +SSH:: + `remote.machine:/path/to/repo.git/` or ++ +`ssh://remote.machine/path/to/repo.git/` ++ +This transport can be used for both uploading and downloading, +and requires you to have a log-in privilege over `ssh` to the +remote machine. It finds out the set of objects the other side +lacks by exchanging the head commits both ends have and +transfers (close to) minimum set of objects. It is by far the +most efficient way to exchange git objects between repositories. + +Local directory:: + `/path/to/repo.git/` ++ +This transport is the same as SSH transport but uses `sh` to run +both ends on the local machine instead of running other end on +the remote machine via `ssh`. + +git Native:: + `git://remote.machine/path/to/repo.git/` ++ +This transport was designed for anonymous downloading. Like SSH +transport, it finds out the set of objects the downstream side +lacks and transfers (close to) minimum set of objects. + +HTTP(S):: + `http://remote.machine/path/to/repo.git/` ++ +Downloader from http and https URL +first obtains the topmost commit object name from the remote site +by looking at the specified refname under `repo.git/refs/` directory, +and then tries to obtain the +commit object by downloading from `repo.git/objects/xx/xxx\...` +using the object name of that commit object. Then it reads the +commit object to find out its parent commits and the associate +tree object; it repeats this process until it gets all the +necessary objects. Because of this behavior, they are +sometimes also called 'commit walkers'. ++ +The 'commit walkers' are sometimes also called 'dumb +transports', because they do not require any git aware smart +server like git Native transport does. Any stock HTTP server +that does not even support directory index would suffice. But +you must prepare your repository with `git-update-server-info` +to help dumb transport downloaders. ++ +There are (confusingly enough) `git-ssh-fetch` and `git-ssh-upload` +programs, which are 'commit walkers'; they outlived their +usefulness when git Native and SSH transports were introduced, +and not used by `git pull` or `git push` scripts. + +Once you fetch from the remote repository, you `resolve` that +with your current branch. + +However -- it's such a common thing to `fetch` and then +immediately `resolve`, that it's called `git pull`, and you can +simply do + +---------------- +$ git pull +---------------- + +and optionally give a branch-name for the remote end as a second +argument. + +[NOTE] +You could do without using any branches at all, by +keeping as many local repositories as you would like to have +branches, and merging between them with `git pull`, just like +you merge between branches. The advantage of this approach is +that it lets you keep set of files for each `branch` checked +out and you may find it easier to switch back and forth if you +juggle multiple lines of development simultaneously. Of +course, you will pay the price of more disk usage to hold +multiple working trees, but disk space is cheap these days. + +[NOTE] +You could even pull from your own repository by +giving '.' as parameter to `git pull`. This +is useful when you want to merge a local branch (or more, if you +are making an Octopus) into the current branch. + +It is likely that you will be pulling from the same remote +repository from time to time. As a short hand, you can store +the remote repository URL in a file under .git/remotes/ +directory, like this: + +------------------------------------------------ +$ mkdir -p .git/remotes/ +$ cat >.git/remotes/linus <<\EOF +URL: http://www.kernel.org/pub/scm/git/git.git/ +EOF +------------------------------------------------ + +and use the filename to `git pull` instead of the full URL. +The URL specified in such file can even be a prefix +of a full URL, like this: + +------------------------------------------------ +$ cat >.git/remotes/jgarzik <<\EOF +URL: http://www.kernel.org/pub/scm/linux/git/jgarzik/ +EOF +------------------------------------------------ + + +Examples. + +. `git pull linus` +. `git pull linus tag v0.99.1` +. `git pull jgarzik/netdev-2.6.git/ e100` + +the above are equivalent to: + +. `git pull http://www.kernel.org/pub/scm/git/git.git/ HEAD` +. `git pull http://www.kernel.org/pub/scm/git/git.git/ tag v0.99.1` +. `git pull http://www.kernel.org/pub/.../jgarzik/netdev-2.6.git e100` + + +How does the merge work? +------------------------ + +We said this tutorial shows what plumbing does to help you cope +with the porcelain that isn't flushing, but we so far did not +talk about how the merge really works. If you are following +this tutorial the first time, I'd suggest to skip to "Publishing +your work" section and come back here later. + +OK, still with me? To give us an example to look at, let's go +back to the earlier repository with "hello" and "example" file, +and bring ourselves back to the pre-merge state: + +------------ +$ git show-branch --more=3 master mybranch +! [master] Merge work in mybranch + * [mybranch] Merge work in mybranch +-- +-- [master] Merge work in mybranch ++* [master^2] Some work. ++* [master^] Some fun. +------------ + +Remember, before running `git merge`, our `master` head was at +"Some fun." commit, while our `mybranch` head was at "Some +work." commit. + +------------ +$ git checkout mybranch +$ git reset --hard master^2 +$ git checkout master +$ git reset --hard master^ +------------ + +After rewinding, the commit structure should look like this: + +------------ +$ git show-branch +* [master] Some fun. + ! [mybranch] Some work. +-- + + [mybranch] Some work. +* [master] Some fun. +*+ [mybranch^] New day. +------------ + +Now we are ready to experiment with the merge by hand. + +`git merge` command, when merging two branches, uses 3-way merge +algorithm. First, it finds the common ancestor between them. +The command it uses is `git-merge-base`: + +------------ +$ mb=$(git-merge-base HEAD mybranch) +------------ + +The command writes the commit object name of the common ancestor +to the standard output, so we captured its output to a variable, +because we will be using it in the next step. BTW, the common +ancestor commit is the "New day." commit in this case. You can +tell it by: + +------------ +$ git-name-rev $mb +my-first-tag +------------ + +After finding out a common ancestor commit, the second step is +this: + +------------ +$ git-read-tree -m -u $mb HEAD mybranch +------------ + +This is the same `git-read-tree` command we have already seen, +but it takes three trees, unlike previous examples. This reads +the contents of each tree into different 'stage' in the index +file (the first tree goes to stage 1, the second stage 2, +etc.). After reading three trees into three stages, the paths +that are the same in all three stages are 'collapsed' into stage +0. Also paths that are the same in two of three stages are +collapsed into stage 0, taking the SHA1 from either stage 2 or +stage 3, whichever is different from stage 1 (i.e. only one side +changed from the common ancestor). + +After 'collapsing' operation, paths that are different in three +trees are left in non-zero stages. At this point, you can +inspect the index file with this command: + +------------ +$ git-ls-files --stage +100644 7f8b141b65fdcee47321e399a2598a235a032422 0 example +100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1 hello +100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2 hello +100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello +------------ + +In our example of only two files, we did not have unchanged +files so only 'example' resulted in collapsing, but in real-life +large projects, only small number of files change in one commit, +and this 'collapsing' tends to trivially merge most of the paths +fairly quickly, leaving only a handful the real changes in non-zero +stages. + +To look at only non-zero stages, use `\--unmerged` flag: + +------------ +$ git-ls-files --unmerged +100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1 hello +100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2 hello +100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello +------------ + +The next step of merging is to merge these three versions of the +file, using 3-way merge. This is done by giving +`git-merge-one-file` command as one of the arguments to +`git-merge-index` command: + +------------ +$ git-merge-index git-merge-one-file hello +Auto-merging hello. +merge: warning: conflicts during merge +ERROR: Merge conflict in hello. +fatal: merge program failed +------------ + +`git-merge-one-file` script is called with parameters to +describe those three versions, and is responsible to leave the +merge results in the working tree. +It is a fairly straightforward shell script, and +eventually calls `merge` program from RCS suite to perform a +file-level 3-way merge. In this case, `merge` detects +conflicts, and the merge result with conflict marks is left in +the working tree.. This can be seen if you run `ls-files +--stage` again at this point: + +------------ +$ git-ls-files --stage +100644 7f8b141b65fdcee47321e399a2598a235a032422 0 example +100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1 hello +100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2 hello +100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello +------------ + +This is the state of the index file and the working file after +`git merge` returns control back to you, leaving the conflicting +merge for you to resolve. Notice that the path `hello` is still +unmerged, and what you see with `git diff` at this point is +differences since stage 2 (i.e. your version). + + +Publishing your work +-------------------- + +So we can use somebody else's work from a remote repository; but +how can *you* prepare a repository to let other people pull from +it? + +Your do your real work in your working tree that has your +primary repository hanging under it as its `.git` subdirectory. +You *could* make that repository accessible remotely and ask +people to pull from it, but in practice that is not the way +things are usually done. A recommended way is to have a public +repository, make it reachable by other people, and when the +changes you made in your primary working tree are in good shape, +update the public repository from it. This is often called +'pushing'. + +[NOTE] +This public repository could further be mirrored, and that is +how git repositories at `kernel.org` are managed. + +Publishing the changes from your local (private) repository to +your remote (public) repository requires a write privilege on +the remote machine. You need to have an SSH account there to +run a single command, `git-receive-pack`. + +First, you need to create an empty repository on the remote +machine that will house your public repository. This empty +repository will be populated and be kept up-to-date by pushing +into it later. Obviously, this repository creation needs to be +done only once. + +[NOTE] +`git push` uses a pair of programs, +`git-send-pack` on your local machine, and `git-receive-pack` +on the remote machine. The communication between the two over +the network internally uses an SSH connection. + +Your private repository's git directory is usually `.git`, but +your public repository is often named after the project name, +i.e. `.git`. Let's create such a public repository for +project `my-git`. After logging into the remote machine, create +an empty directory: + +------------ +$ mkdir my-git.git +------------ + +Then, make that directory into a git repository by running +`git init-db`, but this time, since its name is not the usual +`.git`, we do things slightly differently: + +------------ +$ GIT_DIR=my-git.git git-init-db +------------ + +Make sure this directory is available for others you want your +changes to be pulled by via the transport of your choice. Also +you need to make sure that you have the `git-receive-pack` +program on the `$PATH`. + +[NOTE] +Many installations of sshd do not invoke your shell as the login +shell when you directly run programs; what this means is that if +your login shell is `bash`, only `.bashrc` is read and not +`.bash_profile`. As a workaround, make sure `.bashrc` sets up +`$PATH` so that you can run `git-receive-pack` program. + +[NOTE] +If you plan to publish this repository to be accessed over http, +you should do `chmod +x my-git.git/hooks/post-update` at this +point. This makes sure that every time you push into this +repository, `git-update-server-info` is run. + +Your "public repository" is now ready to accept your changes. +Come back to the machine you have your private repository. From +there, run this command: + +------------ +$ git push :/path/to/my-git.git master +------------ + +This synchronizes your public repository to match the named +branch head (i.e. `master` in this case) and objects reachable +from them in your current repository. + +As a real example, this is how I update my public git +repository. Kernel.org mirror network takes care of the +propagation to other publicly visible machines: + +------------ +$ git push master.kernel.org:/pub/scm/git/git.git/ +------------ + + +Packing your repository +----------------------- + +Earlier, we saw that one file under `.git/objects/??/` directory +is stored for each git object you create. This representation +is efficient to create atomically and safely, but +not so convenient to transport over the network. Since git objects are +immutable once they are created, there is a way to optimize the +storage by "packing them together". The command + +------------ +$ git repack +------------ + +will do it for you. If you followed the tutorial examples, you +would have accumulated about 17 objects in `.git/objects/??/` +directories by now. `git repack` tells you how many objects it +packed, and stores the packed file in `.git/objects/pack` +directory. + +[NOTE] +You will see two files, `pack-\*.pack` and `pack-\*.idx`, +in `.git/objects/pack` directory. They are closely related to +each other, and if you ever copy them by hand to a different +repository for whatever reason, you should make sure you copy +them together. The former holds all the data from the objects +in the pack, and the latter holds the index for random +access. + +If you are paranoid, running `git-verify-pack` command would +detect if you have a corrupt pack, but do not worry too much. +Our programs are always perfect ;-). + +Once you have packed objects, you do not need to leave the +unpacked objects that are contained in the pack file anymore. + +------------ +$ git prune-packed +------------ + +would remove them for you. + +You can try running `find .git/objects -type f` before and after +you run `git prune-packed` if you are curious. Also `git +count-objects` would tell you how many unpacked objects are in +your repository and how much space they are consuming. + +[NOTE] +`git pull` is slightly cumbersome for HTTP transport, as a +packed repository may contain relatively few objects in a +relatively large pack. If you expect many HTTP pulls from your +public repository you might want to repack & prune often, or +never. + +If you run `git repack` again at this point, it will say +"Nothing to pack". Once you continue your development and +accumulate the changes, running `git repack` again will create a +new pack, that contains objects created since you packed your +repository the last time. We recommend that you pack your project +soon after the initial import (unless you are starting your +project from scratch), and then run `git repack` every once in a +while, depending on how active your project is. + +When a repository is synchronized via `git push` and `git pull` +objects packed in the source repository are usually stored +unpacked in the destination, unless rsync transport is used. +While this allows you to use different packing strategies on +both ends, it also means you may need to repack both +repositories every once in a while. + + +Working with Others +------------------- + +Although git is a truly distributed system, it is often +convenient to organize your project with an informal hierarchy +of developers. Linux kernel development is run this way. There +is a nice illustration (page 17, "Merges to Mainline") in Randy +Dunlap's presentation (`http://tinyurl.com/a2jdg`). + +It should be stressed that this hierarchy is purely *informal*. +There is nothing fundamental in git that enforces the "chain of +patch flow" this hierarchy implies. You do not have to pull +from only one remote repository. + +A recommended workflow for a "project lead" goes like this: + +1. Prepare your primary repository on your local machine. Your + work is done there. + +2. Prepare a public repository accessible to others. ++ +If other people are pulling from your repository over dumb +transport protocols (HTTP), you need to keep this repository +'dumb transport friendly'. After `git init-db`, +`$GIT_DIR/hooks/post-update` copied from the standard templates +would contain a call to `git-update-server-info` but the +`post-update` hook itself is disabled by default -- enable it +with `chmod +x post-update`. This makes sure `git-update-server-info` +keeps the necessary files up-to-date. + +3. Push into the public repository from your primary + repository. + +4. `git repack` the public repository. This establishes a big + pack that contains the initial set of objects as the + baseline, and possibly `git prune` if the transport + used for pulling from your repository supports packed + repositories. + +5. Keep working in your primary repository. Your changes + include modifications of your own, patches you receive via + e-mails, and merges resulting from pulling the "public" + repositories of your "subsystem maintainers". ++ +You can repack this private repository whenever you feel like. + +6. Push your changes to the public repository, and announce it + to the public. + +7. Every once in a while, "git repack" the public repository. + Go back to step 5. and continue working. + + +A recommended work cycle for a "subsystem maintainer" who works +on that project and has an own "public repository" goes like this: + +1. Prepare your work repository, by `git clone` the public + repository of the "project lead". The URL used for the + initial cloning is stored in `.git/remotes/origin`. + +2. Prepare a public repository accessible to others, just like + the "project lead" person does. + +3. Copy over the packed files from "project lead" public + repository to your public repository, unless the "project + lead" repository lives on the same machine as yours. In the + latter case, you can use `objects/info/alternates` file to + point at the repository you are borrowing from. + +4. Push into the public repository from your primary + repository. Run `git repack`, and possibly `git prune` if the + transport used for pulling from your repository supports + packed repositories. + +5. Keep working in your primary repository. Your changes + include modifications of your own, patches you receive via + e-mails, and merges resulting from pulling the "public" + repositories of your "project lead" and possibly your + "sub-subsystem maintainers". ++ +You can repack this private repository whenever you feel +like. + +6. Push your changes to your public repository, and ask your + "project lead" and possibly your "sub-subsystem + maintainers" to pull from it. + +7. Every once in a while, `git repack` the public repository. + Go back to step 5. and continue working. + + +A recommended work cycle for an "individual developer" who does +not have a "public" repository is somewhat different. It goes +like this: + +1. Prepare your work repository, by `git clone` the public + repository of the "project lead" (or a "subsystem + maintainer", if you work on a subsystem). The URL used for + the initial cloning is stored in `.git/remotes/origin`. + +2. Do your work in your repository on 'master' branch. + +3. Run `git fetch origin` from the public repository of your + upstream every once in a while. This does only the first + half of `git pull` but does not merge. The head of the + public repository is stored in `.git/refs/heads/origin`. + +4. Use `git cherry origin` to see which ones of your patches + were accepted, and/or use `git rebase origin` to port your + unmerged changes forward to the updated upstream. + +5. Use `git format-patch origin` to prepare patches for e-mail + submission to your upstream and send it out. Go back to + step 2. and continue. + + +Working with Others, Shared Repository Style +-------------------------------------------- + +If you are coming from CVS background, the style of cooperation +suggested in the previous section may be new to you. You do not +have to worry. git supports "shared public repository" style of +cooperation you are probably more familiar with as well. + +See link:cvs-migration.txt[git for CVS users] for the details. + +Bundling your work together +--------------------------- + +It is likely that you will be working on more than one thing at +a time. It is easy to manage those more-or-less independent tasks +using branches with git. + +We have already seen how branches work previously, +with "fun and work" example using two branches. The idea is the +same if there are more than two branches. Let's say you started +out from "master" head, and have some new code in the "master" +branch, and two independent fixes in the "commit-fix" and +"diff-fix" branches: + +------------ +$ git show-branch +! [commit-fix] Fix commit message normalization. + ! [diff-fix] Fix rename detection. + * [master] Release candidate #1 +--- + + [diff-fix] Fix rename detection. + + [diff-fix~1] Better common substring algorithm. ++ [commit-fix] Fix commit message normalization. + * [master] Release candidate #1 +++* [diff-fix~2] Pretty-print messages. +------------ + +Both fixes are tested well, and at this point, you want to merge +in both of them. You could merge in 'diff-fix' first and then +'commit-fix' next, like this: + +------------ +$ git merge 'Merge fix in diff-fix' master diff-fix +$ git merge 'Merge fix in commit-fix' master commit-fix +------------ + +Which would result in: + +------------ +$ git show-branch +! [commit-fix] Fix commit message normalization. + ! [diff-fix] Fix rename detection. + * [master] Merge fix in commit-fix +--- + - [master] Merge fix in commit-fix ++ * [commit-fix] Fix commit message normalization. + - [master~1] Merge fix in diff-fix + +* [diff-fix] Fix rename detection. + +* [diff-fix~1] Better common substring algorithm. + * [master~2] Release candidate #1 +++* [master~3] Pretty-print messages. +------------ + +However, there is no particular reason to merge in one branch +first and the other next, when what you have are a set of truly +independent changes (if the order mattered, then they are not +independent by definition). You could instead merge those two +branches into the current branch at once. First let's undo what +we just did and start over. We would want to get the master +branch before these two merges by resetting it to 'master~2': + +------------ +$ git reset --hard master~2 +------------ + +You can make sure 'git show-branch' matches the state before +those two 'git merge' you just did. Then, instead of running +two 'git merge' commands in a row, you would pull these two +branch heads (this is known as 'making an Octopus'): + +------------ +$ git pull . commit-fix diff-fix +$ git show-branch +! [commit-fix] Fix commit message normalization. + ! [diff-fix] Fix rename detection. + * [master] Octopus merge of branches 'diff-fix' and 'commit-fix' +--- + - [master] Octopus merge of branches 'diff-fix' and 'commit-fix' ++ * [commit-fix] Fix commit message normalization. + +* [diff-fix] Fix rename detection. + +* [diff-fix~1] Better common substring algorithm. + * [master~1] Release candidate #1 +++* [master~2] Pretty-print messages. +------------ + +Note that you should not do Octopus because you can. An octopus +is a valid thing to do and often makes it easier to view the +commit history if you are pulling more than two independent +changes at the same time. However, if you have merge conflicts +with any of the branches you are merging in and need to hand +resolve, that is an indication that the development happened in +those branches were not independent after all, and you should +merge two at a time, documenting how you resolved the conflicts, +and the reason why you preferred changes made in one side over +the other. Otherwise it would make the project history harder +to follow, not easier. + +[ to be continued.. cvsimports ] diff --git a/Documentation/cvs-migration.txt b/Documentation/cvs-migration.txt new file mode 100644 index 00000000..1fbca831 --- /dev/null +++ b/Documentation/cvs-migration.txt @@ -0,0 +1,304 @@ +git for CVS users +================= + +So you're a CVS user. That's OK, it's a treatable condition. The job of +this document is to put you on the road to recovery, by helping you +convert an existing cvs repository to git, and by showing you how to use a +git repository in a cvs-like fashion. + +Some basic familiarity with git is required. This +link:tutorial.html[tutorial introduction to git] should be sufficient. + +First, note some ways that git differs from CVS: + + * Commits are atomic and project-wide, not per-file as in CVS. + + * Offline work is supported: you can make multiple commits locally, + then submit them when you're ready. + + * Branching is fast and easy. + + * Every working tree contains a repository with a full copy of the + project history, and no repository is inherently more important than + any other. However, you can emulate the CVS model by designating a + single shared repository which people can synchronize with; see below + for details. + +Importing a CVS archive +----------------------- + +First, install version 2.1 or higher of cvsps from +link:http://www.cobite.com/cvsps/[http://www.cobite.com/cvsps/] and make +sure it is in your path. The magic command line is then + +------------------------------------------- +$ git cvsimport -v -d -C +------------------------------------------- + +This puts a git archive of the named CVS module in the directory +, which will be created if necessary. The -v option makes +the conversion script very chatty. + +The import checks out from CVS every revision of every file. Reportedly +cvsimport can average some twenty revisions per second, so for a +medium-sized project this should not take more than a couple of minutes. +Larger projects or remote repositories may take longer. + +The main trunk is stored in the git branch named `origin`, and additional +CVS branches are stored in git branches with the same names. The most +recent version of the main trunk is also left checked out on the `master` +branch, so you can start adding your own changes right away. + +The import is incremental, so if you call it again next month it will +fetch any CVS updates that have been made in the meantime. For this to +work, you must not modify the imported branches; instead, create new +branches for your own changes, and merge in the imported branches as +necessary. + +Development Models +------------------ + +CVS users are accustomed to giving a group of developers commit access to +a common repository. In the next section we'll explain how to do this +with git. However, the distributed nature of git allows other development +models, and you may want to first consider whether one of them might be a +better fit for your project. + +For example, you can choose a single person to maintain the project's +primary public repository. Other developers then clone this repository +and each work in their own clone. When they have a series of changes that +they're happy with, they ask the maintainer to pull from the branch +containing the changes. The maintainer reviews their changes and pulls +them into the primary repository, which other developers pull from as +necessary to stay coordinated. The Linux kernel and other projects use +variants of this model. + +With a small group, developers may just pull changes from each other's +repositories without the need for a central maintainer. + +Emulating the CVS Development Model +----------------------------------- + +Start with an ordinary git working directory containing the project, and +remove the checked-out files, keeping just the bare .git directory: + +------------------------------------------------ +$ mv project/.git /pub/repo.git +$ rm -r project/ +------------------------------------------------ + +Next, give every team member read/write access to this repository. One +easy way to do this is to give all the team members ssh access to the +machine where the repository is hosted. If you don't want to give them a +full shell on the machine, there is a restricted shell which only allows +users to do git pushes and pulls; see gitlink:git-shell[1]. + +Put all the committers should in the same group, and make the repository +writable by that group: + +------------------------------------------------ +$ chgrp -R $group repo.git +$ find repo.git -mindepth 1 -type d |xargs chmod ug+rwx,g+s +$ GIT_DIR=repo.git git repo-config core.sharedrepository true +------------------------------------------------ + +Make sure committers have a umask of at most 027, so that the directories +they create are writable and searchable by other group members. + +Suppose this repository is now set up in /pub/repo.git on the host +foo.com. Then as an individual committer you can clone the shared +repository: + +------------------------------------------------ +$ git clone foo.com:/pub/repo.git/ my-project +$ cd my-project +------------------------------------------------ + +and hack away. The equivalent of `cvs update` is + +------------------------------------------------ +$ git pull origin +------------------------------------------------ + +which merges in any work that others might have done since the clone +operation. + +[NOTE] +================================ +The first `git clone` places the following in the +`my-project/.git/remotes/origin` file, and that's why the previous step +and the next step both work. +------------ +URL: foo.com:/pub/project.git/ my-project +Pull: master:origin +------------ +================================ + +You can update the shared repository with your changes using: + +------------------------------------------------ +$ git push origin master +------------------------------------------------ + +If someone else has updated the repository more recently, `git push`, like +`cvs commit`, will complain, in which case you must pull any changes +before attempting the push again. + +In the `git push` command above we specify the name of the remote branch +to update (`master`). If we leave that out, `git push` tries to update +any branches in the remote repository that have the same name as a branch +in the local repository. So the last `push` can be done with either of: + +------------ +$ git push origin +$ git push repo.shared.xz:/pub/scm/project.git/ +------------ + +as long as the shared repository does not have any branches +other than `master`. + +[NOTE] +============ +Because of this behavior, if the shared repository and the developer's +repository both have branches named `origin`, then a push like the above +attempts to update the `origin` branch in the shared repository from the +developer's `origin` branch. The results may be unexpected, so it's +usually best to remove any branch named `origin` from the shared +repository. +============ + +Advanced Shared Repository Management +------------------------------------- + +Git allows you to specify scripts called "hooks" to be run at certain +points. You can use these, for example, to send all commits to the shared +repository to a mailing list. See link:hooks.txt[Hooks used by git]. + +You can enforce finer grained permissions using update hooks. See +link:howto/update-hook-example.txt[Controlling access to branches using +update hooks]. + +CVS annotate +------------ + +So, something has gone wrong, and you don't know whom to blame, and +you're an ex-CVS user and used to do "cvs annotate" to see who caused +the breakage. You're looking for the "git annotate", and it's just +claiming not to find such a script. You're annoyed. + +Yes, that's right. Core git doesn't do "annotate", although it's +technically possible, and there are at least two specialized scripts out +there that can be used to get equivalent information (see the git +mailing list archives for details). + +git has a couple of alternatives, though, that you may find sufficient +or even superior depending on your use. One is called "git-whatchanged" +(for obvious reasons) and the other one is called "pickaxe" ("a tool for +the software archaeologist"). + +The "git-whatchanged" script is a truly trivial script that can give you +a good overview of what has changed in a file or a directory (or an +arbitrary list of files or directories). The "pickaxe" support is an +additional layer that can be used to further specify exactly what you're +looking for, if you already know the specific area that changed. + +Let's step back a bit and think about the reason why you would +want to do "cvs annotate a-file.c" to begin with. + +You would use "cvs annotate" on a file when you have trouble +with a function (or even a single "if" statement in a function) +that happens to be defined in the file, which does not do what +you want it to do. And you would want to find out why it was +written that way, because you are about to modify it to suit +your needs, and at the same time you do not want to break its +current callers. For that, you are trying to find out why the +original author did things that way in the original context. + +Many times, it may be enough to see the commit log messages of +commits that touch the file in question, possibly along with the +patches themselves, like this: + + $ git-whatchanged -p a-file.c + +This will show log messages and patches for each commit that +touches a-file. + +This, however, may not be very useful when this file has many +modifications that are not related to the piece of code you are +interested in. You would see many log messages and patches that +do not have anything to do with the piece of code you are +interested in. As an example, assuming that you have this piece +of code that you are interested in in the HEAD version: + + if (frotz) { + nitfol(); + } + +you would use git-rev-list and git-diff-tree like this: + + $ git-rev-list HEAD | + git-diff-tree --stdin -v -p -S'if (frotz) { + nitfol(); + }' + +We have already talked about the "\--stdin" form of git-diff-tree +command that reads the list of commits and compares each commit +with its parents (otherwise you should go back and read the tutorial). +The git-whatchanged command internally runs +the equivalent of the above command, and can be used like this: + + $ git-whatchanged -p -S'if (frotz) { + nitfol(); + }' + +When the -S option is used, git-diff-tree command outputs +differences between two commits only if one tree has the +specified string in a file and the corresponding file in the +other tree does not. The above example looks for a commit that +has the "if" statement in it in a file, but its parent commit +does not have it in the same shape in the corresponding file (or +the other way around, where the parent has it and the commit +does not), and the differences between them are shown, along +with the commit message (thanks to the -v flag). It does not +show anything for commits that do not touch this "if" statement. + +Also, in the original context, the same statement might have +appeared at first in a different file and later the file was +renamed to "a-file.c". CVS annotate would not help you to go +back across such a rename, but git would still help you in such +a situation. For that, you can give the -C flag to +git-diff-tree, like this: + + $ git-whatchanged -p -C -S'if (frotz) { + nitfol(); + }' + +When the -C flag is used, file renames and copies are followed. +So if the "if" statement in question happens to be in "a-file.c" +in the current HEAD commit, even if the file was originally +called "o-file.c" and then renamed in an earlier commit, or if +the file was created by copying an existing "o-file.c" in an +earlier commit, you will not lose track. If the "if" statement +did not change across such a rename or copy, then the commit that +does rename or copy would not show in the output, and if the +"if" statement was modified while the file was still called +"o-file.c", it would find the commit that changed the statement +when it was in "o-file.c". + +NOTE: The current version of "git-diff-tree -C" is not eager + enough to find copies, and it will miss the fact that a-file.c + was created by copying o-file.c unless o-file.c was somehow + changed in the same commit. + +You can use the --pickaxe-all flag in addition to the -S flag. +This causes the differences from all the files contained in +those two commits, not just the differences between the files +that contain this changed "if" statement: + + $ git-whatchanged -p -C -S'if (frotz) { + nitfol(); + }' --pickaxe-all + +NOTE: This option is called "--pickaxe-all" because -S + option is internally called "pickaxe", a tool for software + archaeologists. diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt new file mode 100644 index 00000000..617d8f52 --- /dev/null +++ b/Documentation/diff-format.txt @@ -0,0 +1,197 @@ +The output format from "git-diff-index", "git-diff-tree" and +"git-diff-files" are very similar. + +These commands all compare two sets of things; what is +compared differs: + +git-diff-index :: + compares the and the files on the filesystem. + +git-diff-index --cached :: + compares the and the index. + +git-diff-tree [-r] [...]:: + compares the trees named by the two arguments. + +git-diff-files [...]:: + compares the index and the files on the filesystem. + + +An output line is formatted this way: + +------------------------------------------------ +in-place edit :100644 100644 bcd1234... 0123456... M file0 +copy-edit :100644 100644 abcd123... 1234567... C68 file1 file2 +rename-edit :100644 100644 abcd123... 1234567... R86 file1 file3 +create :000000 100644 0000000... 1234567... A file4 +delete :100644 000000 1234567... 0000000... D file5 +unmerged :000000 000000 0000000... 0000000... U file6 +------------------------------------------------ + +That is, from the left to the right: + +. a colon. +. mode for "src"; 000000 if creation or unmerged. +. a space. +. mode for "dst"; 000000 if deletion or unmerged. +. a space. +. sha1 for "src"; 0\{40\} if creation or unmerged. +. a space. +. sha1 for "dst"; 0\{40\} if creation, unmerged or "look at work tree". +. a space. +. status, followed by optional "score" number. +. a tab or a NUL when '-z' option is used. +. path for "src" +. a tab or a NUL when '-z' option is used; only exists for C or R. +. path for "dst"; only exists for C or R. +. an LF or a NUL when '-z' option is used, to terminate the record. + + is shown as all 0's if a file is new on the filesystem +and it is out of sync with the index. + +Example: + +------------------------------------------------ +:100644 100644 5be4a4...... 000000...... M file.c +------------------------------------------------ + +When `-z` option is not used, TAB, LF, and backslash characters +in pathnames are represented as `\t`, `\n`, and `\\`, +respectively. + + +Generating patches with -p +-------------------------- + +When "git-diff-index", "git-diff-tree", or "git-diff-files" are run +with a '-p' option, they do not produce the output described above; +instead they produce a patch file. + +The patch generation can be customized at two levels. + +1. When the environment variable 'GIT_EXTERNAL_DIFF' is not set, + these commands internally invoke "diff" like this: + + diff -L a/ -L b/ -pu ++ +For added files, `/dev/null` is used for . For removed +files, `/dev/null` is used for ++ +The "diff" formatting options can be customized via the +environment variable 'GIT_DIFF_OPTS'. For example, if you +prefer context diff: + + GIT_DIFF_OPTS=-c git-diff-index -p HEAD + + +2. When the environment variable 'GIT_EXTERNAL_DIFF' is set, the + program named by it is called, instead of the diff invocation + described above. ++ +For a path that is added, removed, or modified, +'GIT_EXTERNAL_DIFF' is called with 7 parameters: + + path old-file old-hex old-mode new-file new-hex new-mode ++ +where: + + -file:: are files GIT_EXTERNAL_DIFF can use to read the + contents of , + -hex:: are the 40-hexdigit SHA1 hashes, + -mode:: are the octal representation of the file modes. + ++ +The file parameters can point at the user's working file +(e.g. `new-file` in "git-diff-files"), `/dev/null` (e.g. `old-file` +when a new file is added), or a temporary file (e.g. `old-file` in the +index). 'GIT_EXTERNAL_DIFF' should not worry about unlinking the +temporary file --- it is removed when 'GIT_EXTERNAL_DIFF' exits. + +For a path that is unmerged, 'GIT_EXTERNAL_DIFF' is called with 1 +parameter, . + + +git specific extension to diff format +------------------------------------- + +What -p option produces is slightly different from the +traditional diff format. + +1. It is preceded with a "git diff" header, that looks like + this: + + diff --git a/file1 b/file2 ++ +The `a/` and `b/` filenames are the same unless rename/copy is +involved. Especially, even for a creation or a deletion, +`/dev/null` is _not_ used in place of `a/` or `b/` filenames. ++ +When rename/copy is involved, `file1` and `file2` show the +name of the source file of the rename/copy and the name of +the file that rename/copy produces, respectively. + +2. It is followed by one or more extended header lines: + + old mode + new mode + deleted file mode + new file mode + copy from + copy to + rename from + rename to + similarity index + dissimilarity index + index .. + +3. TAB, LF, and backslash characters in pathnames are + represented as `\t`, `\n`, and `\\`, respectively. + + +combined diff format +-------------------- + +git-diff-tree and git-diff-files can take '-c' or '--cc' option +to produce 'combined diff', which looks like this: + +------------ +diff --combined describe.c +@@@ +98,7 @@@ + return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1; + } + +- static void describe(char *arg) + -static void describe(struct commit *cmit, int last_one) +++static void describe(char *arg, int last_one) + { + + unsigned char sha1[20]; + + struct commit *cmit; +------------ + +Unlike the traditional 'unified' diff format, which shows two +files A and B with a single column that has `-` (minus -- +appears in A but removed in B), `+` (plus -- missing in A but +added to B), or ` ` (space -- unchanged) prefix, this format +compares two or more files file1, file2,... with one file X, and +shows how X differs from each of fileN. One column for each of +fileN is prepended to the output line to note how X's line is +different from it. + +A `-` character in the column N means that the line appears in +fileN but it does not appear in the last file. A `+` character +in the column N means that the line appears in the last file, +and fileN does not have that line. + +In the above example output, the function signature was changed +from both files (hence two `-` removals from both file1 and +file2, plus `++` to mean one line that was added does not appear +in either file1 nor file2). Also two other lines are the same +from file1 but do not appear in file2 (hence prefixed with ` +`). + +When shown by `git diff-tree -c`, it compares the parents of a +merge commit with the merge result (i.e. file1..fileN are the +parents). When shown by `git diff-files -c`, it compares the +two unresolved merge parents with the working tree file +(i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka +"their version"). + diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt new file mode 100644 index 00000000..f523ec2f --- /dev/null +++ b/Documentation/diff-options.txt @@ -0,0 +1,98 @@ +-p:: + Generate patch (see section on generating patches) + +-u:: + Synonym for "-p". + +--patch-with-raw:: + Generate patch but keep also the default raw diff output. + +--stat:: + Generate a diffstat instead of a patch. + +--summary:: + Output a condensed summary of extended header information + such as creations, renames and mode changes. + +--patch-with-stat:: + Generate patch and prepend its diffstat. + +-z:: + \0 line termination on output + +--name-only:: + Show only names of changed files. + +--name-status:: + Show only names and status of changed files. + +--full-index:: + Instead of the first handful characters, show full + object name of pre- and post-image blob on the "index" + line when generating a patch format output. + +--abbrev[=]:: + Instead of showing the full 40-byte hexadecimal object + name in diff-raw format output and diff-tree header + lines, show only handful hexdigits prefix. This is + independent of --full-index option above, which controls + the diff-patch output format. Non default number of + digits can be specified with --abbrev=. + +-B:: + Break complete rewrite changes into pairs of delete and create. + +-M:: + Detect renames. + +-C:: + Detect copies as well as renames. + +--diff-filter=[ACDMRTUXB*]:: + Select only files that are Added (`A`), Copied (`C`), + Deleted (`D`), Modified (`M`), Renamed (`R`), have their + type (mode) changed (`T`), are Unmerged (`U`), are + Unknown (`X`), or have had their pairing Broken (`B`). + Any combination of the filter characters may be used. + When `*` (All-or-none) is added to the combination, all + paths are selected if there is any file that matches + other criteria in the comparison; if there is no file + that matches other criteria, nothing is selected. + +--find-copies-harder:: + For performance reasons, by default, -C option finds copies only + if the original file of the copy was modified in the same + changeset. This flag makes the command + inspect unmodified files as candidates for the source of + copy. This is a very expensive operation for large + projects, so use it with caution. + +-l:: + -M and -C options require O(n^2) processing time where n + is the number of potential rename/copy targets. This + option prevents rename/copy detection from running if + the number of rename/copy targets exceeds the specified + number. + +-S:: + Look for differences that contain the change in . + +--pickaxe-all:: + When -S finds a change, show all the changes in that + changeset, not just the files that contain the change + in . + +--pickaxe-regex:: + Make the not a plain string but an extended POSIX + regex to match. + +-O:: + Output the patch in the order specified in the + , which has one shell glob pattern per line. + +-R:: + Swap two inputs; that is, show differences from index or + on-disk file to tree contents. + +For more detailed explanation on these common options, see also +link:diffcore.html[diffcore documentation]. diff --git a/Documentation/diffcore.txt b/Documentation/diffcore.txt new file mode 100644 index 00000000..cb4e5620 --- /dev/null +++ b/Documentation/diffcore.txt @@ -0,0 +1,275 @@ +Tweaking diff output +==================== +June 2005 + + +Introduction +------------ + +The diff commands git-diff-index, git-diff-files, git-diff-tree, and +git-diff-stages can be told to manipulate differences they find in +unconventional ways before showing diff(1) output. The manipulation +is collectively called "diffcore transformation". This short note +describes what they are and how to use them to produce diff outputs +that are easier to understand than the conventional kind. + + +The chain of operation +---------------------- + +The git-diff-* family works by first comparing two sets of +files: + + - git-diff-index compares contents of a "tree" object and the + working directory (when '\--cached' flag is not used) or a + "tree" object and the index file (when '\--cached' flag is + used); + + - git-diff-files compares contents of the index file and the + working directory; + + - git-diff-tree compares contents of two "tree" objects; + + - git-diff-stages compares contents of blobs at two stages in an + unmerged index file. + +In all of these cases, the commands themselves compare +corresponding paths in the two sets of files. The result of +comparison is passed from these commands to what is internally +called "diffcore", in a format similar to what is output when +the -p option is not used. E.g. + +------------------------------------------------ +in-place edit :100644 100644 bcd1234... 0123456... M file0 +create :000000 100644 0000000... 1234567... A file4 +delete :100644 000000 1234567... 0000000... D file5 +unmerged :000000 000000 0000000... 0000000... U file6 +------------------------------------------------ + +The diffcore mechanism is fed a list of such comparison results +(each of which is called "filepair", although at this point each +of them talks about a single file), and transforms such a list +into another list. There are currently 6 such transformations: + +- diffcore-pathspec +- diffcore-break +- diffcore-rename +- diffcore-merge-broken +- diffcore-pickaxe +- diffcore-order + +These are applied in sequence. The set of filepairs git-diff-\* +commands find are used as the input to diffcore-pathspec, and +the output from diffcore-pathspec is used as the input to the +next transformation. The final result is then passed to the +output routine and generates either diff-raw format (see Output +format sections of the manual for git-diff-\* commands) or +diff-patch format. + + +diffcore-pathspec: For Ignoring Files Outside Our Consideration +--------------------------------------------------------------- + +The first transformation in the chain is diffcore-pathspec, and +is controlled by giving the pathname parameters to the +git-diff-* commands on the command line. The pathspec is used +to limit the world diff operates in. It removes the filepairs +outside the specified set of pathnames. E.g. If the input set +of filepairs included: + +------------------------------------------------ +:100644 100644 bcd1234... 0123456... M junkfile +------------------------------------------------ + +but the command invocation was "git-diff-files myfile", then the +junkfile entry would be removed from the list because only "myfile" +is under consideration. + +Implementation note. For performance reasons, git-diff-tree +uses the pathname parameters on the command line to cull set of +filepairs it feeds the diffcore mechanism itself, and does not +use diffcore-pathspec, but the end result is the same. + + +diffcore-break: For Splitting Up "Complete Rewrites" +---------------------------------------------------- + +The second transformation in the chain is diffcore-break, and is +controlled by the -B option to the git-diff-* commands. This is +used to detect a filepair that represents "complete rewrite" and +break such filepair into two filepairs that represent delete and +create. E.g. If the input contained this filepair: + +------------------------------------------------ +:100644 100644 bcd1234... 0123456... M file0 +------------------------------------------------ + +and if it detects that the file "file0" is completely rewritten, +it changes it to: + +------------------------------------------------ +:100644 000000 bcd1234... 0000000... D file0 +:000000 100644 0000000... 0123456... A file0 +------------------------------------------------ + +For the purpose of breaking a filepair, diffcore-break examines +the extent of changes between the contents of the files before +and after modification (i.e. the contents that have "bcd1234..." +and "0123456..." as their SHA1 content ID, in the above +example). The amount of deletion of original contents and +insertion of new material are added together, and if it exceeds +the "break score", the filepair is broken into two. The break +score defaults to 50% of the size of the smaller of the original +and the result (i.e. if the edit shrinks the file, the size of +the result is used; if the edit lengthens the file, the size of +the original is used), and can be customized by giving a number +after "-B" option (e.g. "-B75" to tell it to use 75%). + + +diffcore-rename: For Detection Renames and Copies +------------------------------------------------- + +This transformation is used to detect renames and copies, and is +controlled by the -M option (to detect renames) and the -C option +(to detect copies as well) to the git-diff-* commands. If the +input contained these filepairs: + +------------------------------------------------ +:100644 000000 0123456... 0000000... D fileX +:000000 100644 0000000... 0123456... A file0 +------------------------------------------------ + +and the contents of the deleted file fileX is similar enough to +the contents of the created file file0, then rename detection +merges these filepairs and creates: + +------------------------------------------------ +:100644 100644 0123456... 0123456... R100 fileX file0 +------------------------------------------------ + +When the "-C" option is used, the original contents of modified files, +and deleted files (and also unmodified files, if the +"\--find-copies-harder" option is used) are considered as candidates +of the source files in rename/copy operation. If the input were like +these filepairs, that talk about a modified file fileY and a newly +created file file0: + +------------------------------------------------ +:100644 100644 0123456... 1234567... M fileY +:000000 100644 0000000... bcd3456... A file0 +------------------------------------------------ + +the original contents of fileY and the resulting contents of +file0 are compared, and if they are similar enough, they are +changed to: + +------------------------------------------------ +:100644 100644 0123456... 1234567... M fileY +:100644 100644 0123456... bcd3456... C100 fileY file0 +------------------------------------------------ + +In both rename and copy detection, the same "extent of changes" +algorithm used in diffcore-break is used to determine if two +files are "similar enough", and can be customized to use +a similarity score different from the default of 50% by giving a +number after the "-M" or "-C" option (e.g. "-M8" to tell it to use +8/10 = 80%). + +Note. When the "-C" option is used with `\--find-copies-harder` +option, git-diff-\* commands feed unmodified filepairs to +diffcore mechanism as well as modified ones. This lets the copy +detector consider unmodified files as copy source candidates at +the expense of making it slower. Without `\--find-copies-harder`, +git-diff-\* commands can detect copies only if the file that was +copied happened to have been modified in the same changeset. + + +diffcore-merge-broken: For Putting "Complete Rewrites" Back Together +-------------------------------------------------------------------- + +This transformation is used to merge filepairs broken by +diffcore-break, and not transformed into rename/copy by +diffcore-rename, back into a single modification. This always +runs when diffcore-break is used. + +For the purpose of merging broken filepairs back, it uses a +different "extent of changes" computation from the ones used by +diffcore-break and diffcore-rename. It counts only the deletion +from the original, and does not count insertion. If you removed +only 10 lines from a 100-line document, even if you added 910 +new lines to make a new 1000-line document, you did not do a +complete rewrite. diffcore-break breaks such a case in order to +help diffcore-rename to consider such filepairs as candidate of +rename/copy detection, but if filepairs broken that way were not +matched with other filepairs to create rename/copy, then this +transformation merges them back into the original +"modification". + +The "extent of changes" parameter can be tweaked from the +default 80% (that is, unless more than 80% of the original +material is deleted, the broken pairs are merged back into a +single modification) by giving a second number to -B option, +like these: + +* -B50/60 (give 50% "break score" to diffcore-break, use 60% + for diffcore-merge-broken). + +* -B/60 (the same as above, since diffcore-break defaults to 50%). + +Note that earlier implementation left a broken pair as a separate +creation and deletion patches. This was an unnecessary hack and +the latest implementation always merges all the broken pairs +back into modifications, but the resulting patch output is +formatted differently for easier review in case of such +a complete rewrite by showing the entire contents of old version +prefixed with '-', followed by the entire contents of new +version prefixed with '+'. + + +diffcore-pickaxe: For Detecting Addition/Deletion of Specified String +--------------------------------------------------------------------- + +This transformation is used to find filepairs that represent +changes that touch a specified string, and is controlled by the +-S option and the `\--pickaxe-all` option to the git-diff-* +commands. + +When diffcore-pickaxe is in use, it checks if there are +filepairs whose "original" side has the specified string and +whose "result" side does not. Such a filepair represents "the +string appeared in this changeset". It also checks for the +opposite case that loses the specified string. + +When `\--pickaxe-all` is not in effect, diffcore-pickaxe leaves +only such filepairs that touch the specified string in its +output. When `\--pickaxe-all` is used, diffcore-pickaxe leaves all +filepairs intact if there is such a filepair, or makes the +output empty otherwise. The latter behaviour is designed to +make reviewing of the changes in the context of the whole +changeset easier. + + +diffcore-order: For Sorting the Output Based on Filenames +--------------------------------------------------------- + +This is used to reorder the filepairs according to the user's +(or project's) taste, and is controlled by the -O option to the +git-diff-* commands. + +This takes a text file each of whose lines is a shell glob +pattern. Filepairs that match a glob pattern on an earlier line +in the file are output before ones that match a later line, and +filepairs that do not match any glob pattern are output last. + +As an example, a typical orderfile for the core git probably +would look like this: + +------------------------------------------------ +README +Makefile +Documentation +*.h +*.c +t +------------------------------------------------ + diff --git a/Documentation/everyday.txt b/Documentation/everyday.txt new file mode 100644 index 00000000..b935c180 --- /dev/null +++ b/Documentation/everyday.txt @@ -0,0 +1,468 @@ +Everyday GIT With 20 Commands Or So +=================================== + +GIT suite has over 100 commands, and the manual page for each of +them discusses what the command does and how it is used in +detail, but until you know what command should be used in order +to achieve what you want to do, you cannot tell which manual +page to look at, and if you know that already you do not need +the manual. + +Does that mean you need to know all of them before you can use +git? Not at all. Depending on the role you play, the set of +commands you need to know is slightly different, but in any case +what you need to learn is far smaller than the full set of +commands to carry out your day-to-day work. This document is to +serve as a cheat-sheet and a set of pointers for people playing +various roles. + +<> commands are needed by people who has a +repository --- that is everybody, because every working tree of +git is a repository. + +In addition, <> commands are +essential for anybody who makes a commit, even for somebody who +works alone. + +If you work with other people, you will need commands listed in +<> section as well. + +People who play <> role need to learn some more +commands in addition to the above. + +<> commands are for system +administrators who are responsible to care and feed git +repositories to support developers. + + +Basic Repository[[Basic Repository]] +------------------------------------ + +Everybody uses these commands to feed and care git repositories. + + * gitlink:git-init-db[1] or gitlink:git-clone[1] to create a + new repository. + + * gitlink:git-fsck-objects[1] to validate the repository. + + * gitlink:git-prune[1] to garbage collect cruft in the + repository. + + * gitlink:git-repack[1] to pack loose objects for efficiency. + +Examples +~~~~~~~~ + +Check health and remove cruft.:: ++ +------------ +$ git fsck-objects <1> +$ git prune +$ git count-objects <2> +$ git repack <3> +$ git prune <4> +------------ ++ +<1> running without "--full" is usually cheap and assures the +repository health reasonably well. +<2> check how many loose objects there are and how much +disk space is wasted by not repacking. +<3> without "-a" repacks incrementally. repacking every 4-5MB +of loose objects accumulation may be a good rule of thumb. +<4> after repack, prune removes the duplicate loose objects. + +Repack a small project into single pack.:: ++ +------------ +$ git repack -a -d <1> +$ git prune +------------ ++ +<1> pack all the objects reachable from the refs into one pack +and remove unneeded other packs + + +Individual Developer (Standalone)[[Individual Developer (Standalone)]] +---------------------------------------------------------------------- + +A standalone individual developer does not exchange patches with +other people, and works alone in a single repository, using the +following commands. + + * gitlink:git-show-branch[1] to see where you are. + + * gitlink:git-log[1] to see what happened. + + * gitlink:git-whatchanged[1] to find out where things have + come from. + + * gitlink:git-checkout[1] and gitlink:git-branch[1] to switch + branches. + + * gitlink:git-add[1] and gitlink:git-update-index[1] to manage + the index file. + + * gitlink:git-diff[1] and gitlink:git-status[1] to see what + you are in the middle of doing. + + * gitlink:git-commit[1] to advance the current branch. + + * gitlink:git-reset[1] and gitlink:git-checkout[1] (with + pathname parameters) to undo changes. + + * gitlink:git-pull[1] with "." as the remote to merge between + local branches. + + * gitlink:git-rebase[1] to maintain topic branches. + + * gitlink:git-tag[1] to mark known point. + +Examples +~~~~~~~~ + +Extract a tarball and create a working tree and a new repository to keep track of it.:: ++ +------------ +$ tar zxf frotz.tar.gz +$ cd frotz +$ git-init-db +$ git add . <1> +$ git commit -m 'import of frotz source tree.' +$ git tag v2.43 <2> +------------ ++ +<1> add everything under the current directory. +<2> make a lightweight, unannotated tag. + +Create a topic branch and develop.:: ++ +------------ +$ git checkout -b alsa-audio <1> +$ edit/compile/test +$ git checkout -- curses/ux_audio_oss.c <2> +$ git add curses/ux_audio_alsa.c <3> +$ edit/compile/test +$ git diff <4> +$ git commit -a -s <5> +$ edit/compile/test +$ git reset --soft HEAD^ <6> +$ edit/compile/test +$ git diff ORIG_HEAD <7> +$ git commit -a -c ORIG_HEAD <8> +$ git checkout master <9> +$ git pull . alsa-audio <10> +$ git log --since='3 days ago' <11> +$ git log v2.43.. curses/ <12> +------------ ++ +<1> create a new topic branch. +<2> revert your botched changes in "curses/ux_audio_oss.c". +<3> you need to tell git if you added a new file; removal and +modification will be caught if you do "commit -a" later. +<4> to see what changes you are committing. +<5> commit everything as you have tested, with your sign-off. +<6> take the last commit back, keeping what is in the working tree. +<7> look at the changes since the premature commit we took back. +<8> redo the commit undone in the previous step, using the message +you originally wrote. +<9> switch to the master branch. +<10> merge a topic branch into your master branch +<11> review commit logs; other forms to limit output can be +combined and include --max-count=10 (show 10 commits), --until='2005-12-10'. +<12> view only the changes that touch what's in curses/ +directory, since v2.43 tag. + + +Individual Developer (Participant)[[Individual Developer (Participant)]] +------------------------------------------------------------------------ + +A developer working as a participant in a group project needs to +learn how to communicate with others, and uses these commands in +addition to the ones needed by a standalone developer. + + * gitlink:git-clone[1] from the upstream to prime your local + repository. + + * gitlink:git-pull[1] and gitlink:git-fetch[1] from "origin" + to keep up-to-date with the upstream. + + * gitlink:git-push[1] to shared repository, if you adopt CVS + style shared repository workflow. + + * gitlink:git-format-patch[1] to prepare e-mail submission, if + you adopt Linux kernel-style public forum workflow. + +Examples +~~~~~~~~ + +Clone the upstream and work on it. Feed changes to upstream.:: ++ +------------ +$ git clone git://git.kernel.org/pub/scm/.../torvalds/linux-2.6 my2.6 +$ cd my2.6 +$ edit/compile/test; git commit -a -s <1> +$ git format-patch origin <2> +$ git pull <3> +$ git whatchanged -p ORIG_HEAD.. arch/i386 include/asm-i386 <4> +$ git pull git://git.kernel.org/pub/.../jgarzik/libata-dev.git ALL <5> +$ git reset --hard ORIG_HEAD <6> +$ git prune <7> +$ git fetch --tags <8> +------------ ++ +<1> repeat as needed. +<2> extract patches from your branch for e-mail submission. +<3> "pull" fetches from "origin" by default and merges into the +current branch. +<4> immediately after pulling, look at the changes done upstream +since last time we checked, only in the +area we are interested in. +<5> fetch from a specific branch from a specific repository and merge. +<6> revert the pull. +<7> garbage collect leftover objects from reverted pull. +<8> from time to time, obtain official tags from the "origin" +and store them under .git/refs/tags/. + + +Push into another repository.:: ++ +------------ +satellite$ git clone mothership:frotz/.git frotz <1> +satellite$ cd frotz +satellite$ cat .git/remotes/origin <2> +URL: mothership:frotz/.git +Pull: master:origin +satellite$ echo 'Push: master:satellite' >>.git/remotes/origin <3> +satellite$ edit/compile/test/commit +satellite$ git push origin <4> + +mothership$ cd frotz +mothership$ git checkout master +mothership$ git pull . satellite <5> +------------ ++ +<1> mothership machine has a frotz repository under your home +directory; clone from it to start a repository on the satellite +machine. +<2> clone creates this file by default. It arranges "git pull" +to fetch and store the master branch head of mothership machine +to local "origin" branch. +<3> arrange "git push" to push local "master" branch to +"satellite" branch of the mothership machine. +<4> push will stash our work away on "satellite" branch on the +mothership machine. You could use this as a back-up method. +<5> on mothership machine, merge the work done on the satellite +machine into the master branch. + +Branch off of a specific tag.:: ++ +------------ +$ git checkout -b private2.6.14 v2.6.14 <1> +$ edit/compile/test; git commit -a +$ git checkout master +$ git format-patch -k -m --stdout v2.6.14..private2.6.14 | + git am -3 -k <2> +------------ ++ +<1> create a private branch based on a well known (but somewhat behind) +tag. +<2> forward port all changes in private2.6.14 branch to master branch +without a formal "merging". + + +Integrator[[Integrator]] +------------------------ + +A fairly central person acting as the integrator in a group +project receives changes made by others, reviews and integrates +them and publishes the result for others to use, using these +commands in addition to the ones needed by participants. + + * gitlink:git-am[1] to apply patches e-mailed in from your + contributors. + + * gitlink:git-pull[1] to merge from your trusted lieutenants. + + * gitlink:git-format-patch[1] to prepare and send suggested + alternative to contributors. + + * gitlink:git-revert[1] to undo botched commits. + + * gitlink:git-push[1] to publish the bleeding edge. + + +Examples +~~~~~~~~ + +My typical GIT day.:: ++ +------------ +$ git status <1> +$ git show-branch <2> +$ mailx <3> +& s 2 3 4 5 ./+to-apply +& s 7 8 ./+hold-linus +& q +$ git checkout master +$ git am -3 -i -s -u ./+to-apply <4> +$ compile/test +$ git checkout -b hold/linus && git am -3 -i -s -u ./+hold-linus <5> +$ git checkout topic/one && git rebase master <6> +$ git checkout pu && git reset --hard master <7> +$ git pull . topic/one topic/two && git pull . hold/linus <8> +$ git checkout maint +$ git cherry-pick master~4 <9> +$ compile/test +$ git tag -s -m 'GIT 0.99.9x' v0.99.9x <10> +$ git fetch ko && git show-branch master maint 'tags/ko-*' <11> +$ git push ko <12> +$ git push ko v0.99.9x <13> +------------ ++ +<1> see what I was in the middle of doing, if any. +<2> see what topic branches I have and think about how ready +they are. +<3> read mails, save ones that are applicable, and save others +that are not quite ready. +<4> apply them, interactively, with my sign-offs. +<5> create topic branch as needed and apply, again with my +sign-offs. +<6> rebase internal topic branch that has not been merged to the +master, nor exposed as a part of a stable branch. +<7> restart "pu" every time from the master. +<8> and bundle topic branches still cooking. +<9> backport a critical fix. +<10> create a signed tag. +<11> make sure I did not accidentally rewind master beyond what I +already pushed out. "ko" shorthand points at the repository I have +at kernel.org, and looks like this: ++ +------------ +$ cat .git/remotes/ko +URL: kernel.org:/pub/scm/git/git.git +Pull: master:refs/tags/ko-master +Pull: maint:refs/tags/ko-maint +Push: master +Push: +pu +Push: maint +------------ ++ +In the output from "git show-branch", "master" should have +everything "ko-master" has. + +<12> push out the bleeding edge. +<13> push the tag out, too. + + +Repository Administration[[Repository Administration]] +------------------------------------------------------ + +A repository administrator uses the following tools to set up +and maintain access to the repository by developers. + + * gitlink:git-daemon[1] to allow anonymous download from + repository. + + * gitlink:git-shell[1] can be used as a 'restricted login shell' + for shared central repository users. + +link:howto/update-hook-example.txt[update hook howto] has a good +example of managing a shared central repository. + + +Examples +~~~~~~~~ +Run git-daemon to serve /pub/scm from inetd.:: ++ +------------ +$ grep git /etc/inetd.conf +git stream tcp nowait nobody \ + /usr/bin/git-daemon git-daemon --inetd --syslog --export-all /pub/scm +------------ ++ +The actual configuration line should be on one line. + +Run git-daemon to serve /pub/scm from xinetd.:: ++ +------------ +$ cat /etc/xinetd.d/git-daemon +# default: off +# description: The git server offers access to git repositories +service git +{ + disable = no + type = UNLISTED + port = 9418 + socket_type = stream + wait = no + user = nobody + server = /usr/bin/git-daemon + server_args = --inetd --syslog --export-all --base-path=/pub/scm + log_on_failure += USERID +} +------------ ++ +Check your xinetd(8) documentation and setup, this is from a Fedora system. +Others might be different. + +Give push/pull only access to developers.:: ++ +------------ +$ grep git /etc/passwd <1> +alice:x:1000:1000::/home/alice:/usr/bin/git-shell +bob:x:1001:1001::/home/bob:/usr/bin/git-shell +cindy:x:1002:1002::/home/cindy:/usr/bin/git-shell +david:x:1003:1003::/home/david:/usr/bin/git-shell +$ grep git /etc/shells <2> +/usr/bin/git-shell +------------ ++ +<1> log-in shell is set to /usr/bin/git-shell, which does not +allow anything but "git push" and "git pull". The users should +get an ssh access to the machine. +<2> in many distributions /etc/shells needs to list what is used +as the login shell. + +CVS-style shared repository.:: ++ +------------ +$ grep git /etc/group <1> +git:x:9418:alice,bob,cindy,david +$ cd /home/devo.git +$ ls -l <2> + lrwxrwxrwx 1 david git 17 Dec 4 22:40 HEAD -> refs/heads/master + drwxrwsr-x 2 david git 4096 Dec 4 22:40 branches + -rw-rw-r-- 1 david git 84 Dec 4 22:40 config + -rw-rw-r-- 1 david git 58 Dec 4 22:40 description + drwxrwsr-x 2 david git 4096 Dec 4 22:40 hooks + -rw-rw-r-- 1 david git 37504 Dec 4 22:40 index + drwxrwsr-x 2 david git 4096 Dec 4 22:40 info + drwxrwsr-x 4 david git 4096 Dec 4 22:40 objects + drwxrwsr-x 4 david git 4096 Nov 7 14:58 refs + drwxrwsr-x 2 david git 4096 Dec 4 22:40 remotes +$ ls -l hooks/update <3> + -r-xr-xr-x 1 david git 3536 Dec 4 22:40 update +$ cat info/allowed-users <4> +refs/heads/master alice\|cindy +refs/heads/doc-update bob +refs/tags/v[0-9]* david +------------ ++ +<1> place the developers into the same git group. +<2> and make the shared repository writable by the group. +<3> use update-hook example by Carl from Documentation/howto/ +for branch policy control. +<4> alice and cindy can push into master, only bob can push into doc-update. +david is the release manager and is the only person who can +create and push version tags. + +HTTP server to support dumb protocol transfer.:: ++ +------------ +dev$ git update-server-info <1> +dev$ ftp user@isp.example.com <2> +ftp> cp -r .git /home/user/myproject.git +------------ ++ +<1> make sure your info/refs and objects/info/packs are up-to-date +<2> upload to public HTTP server hosted by your ISP. diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt new file mode 100644 index 00000000..13f34d3c --- /dev/null +++ b/Documentation/fetch-options.txt @@ -0,0 +1,41 @@ +-a, \--append:: + Append ref names and object names of fetched refs to the + existing contents of `.git/FETCH_HEAD`. Without this + option old data in `.git/FETCH_HEAD` will be overwritten. + +\--upload-pack :: + When given, and the repository to fetch from is handled + by 'git-fetch-pack', '--exec=' is passed to + the command to specify non-default path for the command + run on the other end. + +-f, \--force:: + When `git-fetch` is used with `:` + refspec, it refuses to update the local branch + `` unless the remote branch `` it + fetches is a descendant of ``. This option + overrides that check. + +\--no-tags:: + By default, `git-fetch` fetches tags that point at + objects that are downloaded from the remote repository + and stores them locally. This option disables this + automatic tag following. + +-t, \--tags:: + Most of the tags are fetched automatically as branch + heads are downloaded, but tags that do not point at + objects reachable from the branch heads that are being + tracked will not be fetched by this mechanism. This + flag lets all tags and their associated objects be + downloaded. + +-k, \--keep:: + Keep downloaded pack. + +-u, \--update-head-ok:: + By default `git-fetch` refuses to update the head which + corresponds to the current branch. This flag disables the + check. Note that fetching into the current branch will not + update the index and working directory, so use it with care. + diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt new file mode 100644 index 00000000..6342ea33 --- /dev/null +++ b/Documentation/git-add.txt @@ -0,0 +1,86 @@ +git-add(1) +========== + +NAME +---- +git-add - Add files to the index file + +SYNOPSIS +-------- +'git-add' [-n] [-v] [--] ... + +DESCRIPTION +----------- +A simple wrapper for git-update-index to add files to the index, +for people used to do "cvs add". + +It only adds non-ignored files, to add ignored files use +"git update-index --add". + +OPTIONS +------- +...:: + Files to add to the index (see gitlink:git-ls-files[1]). + +-n:: + Don't actually add the file(s), just show if they exist. + +-v:: + Be verbose. + +\--:: + This option can be used to separate command-line options from + the list of files, (useful when filenames might be mistaken + for command-line options). + + +DISCUSSION +---------- + +The list of given to the command is fed to `git-ls-files` +command to list files that are not registered in the index and +are not ignored/excluded by `$GIT_DIR/info/exclude` file or +`.gitignore` file in each directory. This means two things: + +. You can put the name of a directory on the command line, and + the command will add all files in it and its subdirectories; + +. Giving the name of a file that is already in index does not + run `git-update-index` on that path. + + +EXAMPLES +-------- +git-add Documentation/\\*.txt:: + + Adds all `\*.txt` files that are not in the index under + `Documentation` directory and its subdirectories. ++ +Note that the asterisk `\*` is quoted from the shell in this +example; this lets the command to include the files from +subdirectories of `Documentation/` directory. + +git-add git-*.sh:: + + Adds all git-*.sh scripts that are not in the index. + Because this example lets shell expand the asterisk + (i.e. you are listing the files explicitly), it does not + add `subdir/git-foo.sh` to the index. + +See Also +-------- +gitlink:git-rm[1] +gitlink:git-ls-files[1] + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by Junio C Hamano and the git-list . + +GIT +--- +Part of the gitlink:git[7] suite + diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt new file mode 100644 index 00000000..910457d3 --- /dev/null +++ b/Documentation/git-am.txt @@ -0,0 +1,102 @@ +git-am(1) +========= + +NAME +---- +git-am - Apply a series of patches in a mailbox + + +SYNOPSIS +-------- +[verse] +'git-am' [--signoff] [--dotest=] [--utf8] [--binary] [--3way] + [--interactive] [--whitespace=