diff --git a/BreakingChanges.adoc b/BreakingChanges.adoc new file mode 100644 index 000000000..f814450d2 --- /dev/null +++ b/BreakingChanges.adoc @@ -0,0 +1,335 @@ += Upcoming breaking changes + +The Git project aims to ensure backwards compatibility to the best extent +possible. Minor releases will not break backwards compatibility unless there is +a very strong reason to do so, like for example a security vulnerability. + +Regardless of that, due to the age of the Git project, it is only natural to +accumulate a backlog of backwards-incompatible changes that will eventually be +required to keep the project aligned with a changing world. These changes fall +into several categories: + +* Changes to long established defaults. +* Concepts that have been replaced with a superior design. +* Concepts, commands, configuration or options that have been lacking in major + ways and that cannot be fixed and which will thus be removed without any + replacement. + +Explicitly not included in this list are fixes to minor bugs that may cause a +change in user-visible behavior. + +The Git project irregularly releases breaking versions that deliberately break +backwards compatibility with older versions. This is done to ensure that Git +remains relevant, safe and maintainable going forward. The release cadence of +breaking versions is typically measured in multiple years. We had the following +major breaking releases in the past: + +* Git 1.6.0, released in August 2008. +* Git 2.0, released in May 2014. + +We use . release numbers these days, starting from Git 2.0. For +future releases, our plan is to increment in the release number when we +make the next breaking release. Before Git 2.0, the release numbers were +1.. with the intention to increment for "usual" breaking +releases, reserving the jump to Git 2.0 for really large backward-compatibility +breaking changes. + +The intent of this document is to track upcoming deprecations for future +breaking releases. Furthermore, this document also tracks what will _not_ be +deprecated. This is done such that the outcome of discussions document both +when the discussion favors deprecation, but also when it rejects a deprecation. + +Items should have a clear summary of the reasons why we do or do not want to +make the described change that can be easily understood without having to read +the mailing list discussions. If there are alternatives to the changed feature, +those alternatives should be pointed out to our users. + +All items should be accompanied by references to relevant mailing list threads +where the deprecation was discussed. These references use message-IDs, which +can visited via + + https://lore.kernel.org/git/$message_id/ + +to see the message and its surrounding discussion. Such a reference is there to +make it easier for you to find how the project reached consensus on the +described item back then. + +This is a living document as the environment surrounding the project changes +over time. If circumstances change, an earlier decision to deprecate or change +something may need to be revisited from time to time. So do not take items on +this list to mean "it is settled, do not waste our time bringing it up again". + +== Procedure + +Discussing the desire to make breaking changes, declaring that breaking +changes are made at a certain version boundary, and recording these +decisions in this document, are necessary but not sufficient. +Because such changes are expected to be numerous, and the design and +implementation of them are expected to span over time, they have to +be deployable trivially at such a version boundary, prepared over long +time. + +The breaking changes MUST be guarded with the a compile-time switch, +WITH_BREAKING_CHANGES, to help this process. When built with it, +the resulting Git binary together with its documentation would +behave as if these breaking changes slated for the next big version +boundary are already in effect. We also have a CI job to exercise +the work-in-progress version of Git with these breaking changes. + + +== Git 3.0 + +The following subsections document upcoming breaking changes for Git 3.0. There +is no planned release date for this breaking version yet. + +Proposed changes and removals only include items which are "ready" to be done. +In other words, this is not supposed to be a wishlist of features that should +be changed to or replaced in case the alternative was implemented already. + +=== Changes + +* The default hash function for new repositories will be changed from "sha1" + to "sha256". SHA-1 has been deprecated by NIST in 2011 and is nowadays + recommended against in FIPS 140-2 and similar certifications. Furthermore, + there are practical attacks on SHA-1 that weaken its cryptographic properties: ++ + ** The SHAppening (2015). The first demonstration of a practical attack + against SHA-1 with 2^57 operations. + ** SHAttered (2017). Generation of two valid PDF files with 2^63 operations. + ** Birthday-Near-Collision (2019). This attack allows for chosen prefix + attacks with 2^68 operations. + ** Shambles (2020). This attack allows for chosen prefix attacks with 2^63 + operations. ++ +While we have protections in place against known attacks, it is expected +that more attacks against SHA-1 will be found by future research. Paired +with the ever-growing capability of hardware, it is only a matter of time +before SHA-1 will be considered broken completely. We want to be prepared +and will thus change the default hash algorithm to "sha256" for newly +initialized repositories. ++ +An important requirement for this change is that the ecosystem is ready to +support the "sha256" object format. This includes popular Git libraries, +applications and forges. ++ +There is no plan to deprecate the "sha1" object format at this point in time. ++ +Cf. <2f5de416-04ba-c23d-1e0b-83bb655829a7@zombino.com>, +<20170223155046.e7nxivfwqqoprsqj@LykOS.localdomain>, +. + +* The default storage format for references in newly created repositories will + be changed from "files" to "reftable". The "reftable" format provides + multiple advantages over the "files" format: ++ + ** It is impossible to store two references that only differ in casing on + case-insensitive filesystems with the "files" format. This issue is common + on Windows and macOS platforms. As the "reftable" backend does not use + filesystem paths to encode reference names this problem goes away. + ** Similarly, macOS normalizes path names that contain unicode characters, + which has the consequence that you cannot store two names with unicode + characters that are encoded differently with the "files" backend. Again, + this is not an issue with the "reftable" backend. + ** Deleting references with the "files" backend requires Git to rewrite the + complete "packed-refs" file. In large repositories with many references + this file can easily be dozens of megabytes in size, in extreme cases it + may be gigabytes. The "reftable" backend uses tombstone markers for + deleted references and thus does not have to rewrite all of its data. + ** Repository housekeeping with the "files" backend typically performs + all-into-one repacks of references. This can be quite expensive, and + consequently housekeeping is a tradeoff between the number of loose + references that accumulate and slow down operations that read references, + and compressing those loose references into the "packed-refs" file. The + "reftable" backend uses geometric compaction after every write, which + amortizes costs and ensures that the backend is always in a + well-maintained state. + ** Operations that write multiple references at once are not atomic with the + "files" backend. Consequently, Git may see in-between states when it reads + references while a reference transaction is in the process of being + committed to disk. + ** Writing many references at once is slow with the "files" backend because + every reference is created as a separate file. The "reftable" backend + significantly outperforms the "files" backend by multiple orders of + magnitude. + ** The reftable backend uses a binary format with prefix compression for + reference names. As a result, the format uses less space compared to the + "packed-refs" file. ++ +Users that get immediate benefit from the "reftable" backend could continue to +opt-in to the "reftable" format manually by setting the "init.defaultRefFormat" +config. But defaults matter, and we think that overall users will have a better +experience with less platform-specific quirks when they use the new backend by +default. ++ +A prerequisite for this change is that the ecosystem is ready to support the +"reftable" format. Most importantly, alternative implementations of Git like +JGit, libgit2 and Gitoxide need to support it. + +* In new repositories, the default branch name will be `main`. We have been + warning that the default name will change since 675704c74dd (init: + provide useful advice about init.defaultBranch, 2020-12-11). The new name + matches the default branch name used in new repositories by many of the + big Git forges. + +* Git will require Rust as a mandatory part of the build process. While Git + already started to adopt Rust in Git 2.49, all parts written in Rust are + optional for the time being. This includes: ++ + ** The Rust wrapper around libgit.a that is part of "contrib/" and which has + been introduced in Git 2.49. + ** Subsystems that have an alternative implementation in Rust to test + interoperability between our C and Rust codebase. + ** Newly written features that are not mission critical for a fully functional + Git client. ++ +These changes are meant as test balloons to allow distributors of Git to prepare +for Rust becoming a mandatory part of the build process. There will be multiple +milestones for the introduction of Rust: ++ +-- +1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and + disabled in our Makefile so that the project can sort out the initial + infrastructure. +2. In Git 2.53, both build systems will default-enable support for Rust. + Consequently, builds will break by default if Rust is not available on the + build host. The use of Rust can still be explicitly disabled via build + flags. +3. In Git 3.0, the build options will be removed and support for Rust is + mandatory. +-- ++ +You can explicitly ask both Meson and our Makefile-based system to enable Rust +by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`, +respectively. ++ +The Git project will declare the last version before Git 3.0 to be a long-term +support release. This long-term release will receive important bug fixes for at +least four release cycles and security fixes for six release cycles. The Git +project will hand over maintainership of the long-term release to distributors +in case they need to extend the life of that long-term release even further. +Details of how this long-term release will be handed over to the community will +be discussed once the Git project decides to stop officially supporting it. ++ +We will evaluate the impact on downstream distributions before making Rust +mandatory in Git 3.0. If we see that the impact on downstream distributions +would be significant, we may decide to defer this change to a subsequent minor +release. This evaluation will also take into account our own experience with +how painful it is to keep Rust an optional component. + +=== Removals + +* Support for grafting commits has long been superseded by git-replace(1). + Grafts are inferior to replacement refs: ++ + ** Grafts are a local-only mechanism and cannot be shared across + repositories. + ** Grafts can lead to hard-to-diagnose problems when transferring objects + between repositories. ++ +The grafting mechanism has been marked as outdated since e650d0643b (docs: mark +info/grafts as outdated, 2014-03-05) and will be removed. ++ +Cf. <20140304174806.GA11561@sigill.intra.peff.net>. + +* The git-pack-redundant(1) command can be used to remove redundant pack files. + The subcommand is unusably slow and the reason why nobody reports it as a + performance bug is suspected to be the absence of users. We have nominated + the command for removal and have started to emit a user-visible warning in + c3b58472be (pack-redundant: gauge the usage before proposing its removal, + 2020-08-25) whenever the command is executed. ++ +So far there was a single complaint about somebody still using the command, but +that complaint did not cause us to reverse course. On the contrary, we have +doubled down on the deprecation and starting with 4406522b76 (pack-redundant: +escalate deprecation warning to an error, 2023-03-23), the command dies unless +the user passes the `--i-still-use-this` option. ++ +There have not been any subsequent complaints, so this command will finally be +removed. ++ +Cf. , + , + <20230323204047.GA9290@coredump.intra.peff.net>, + +* Support for storing shorthands for remote URLs in "$GIT_COMMON_DIR/branches/" + and "$GIT_COMMON_DIR/remotes/" has been long superseded by storing remotes in + the repository configuration. ++ +The mechanism has originally been introduced in f170e4b39d ([PATCH] fetch/pull: +short-hand notation for remote repositories., 2005-07-16) and was superseded by +6687f8fea2 ([PATCH] Use .git/remote/origin, not .git/branches/origin., +2005-08-20), where we switched from ".git/branches/" to ".git/remotes/". That +commit already mentions an upcoming deprecation of the ".git/branches/" +directory, and starting with a1d4aa7424 (Add repository-layout document., +2005-09-01) we have also marked this layout as deprecated. Eventually we also +started to migrate away from ".git/remotes/" in favor of config-based remotes, +and we have marked the directory as legacy in 3d3d282146 (Documentation: +Grammar correction, wording fixes and cleanup, 2011-08-23) ++ +As our documentation mentions, these directories are unlikely to be used in +modern repositories and most users aren't even aware of these mechanisms. They +have been deprecated for almost 20 years and 14 years respectively, and we are +not aware of any active users that have complained about this deprecation. +Furthermore, the ".git/branches/" directory is nowadays misleadingly named and +may cause confusion as "branches" are almost exclusively used in the context of +references. ++ +These features will be removed. + +* Support for "--stdin" option in the "name-rev" command was + deprecated (and hidden from the documentation) in the Git 2.40 + timeframe, in preference to its synonym "--annotate-stdin". Git 3.0 + removes the support for "--stdin" altogether. + +* The git-whatchanged(1) command has outlived its usefulness more than + 10 years ago, and takes more keystrokes to type than its rough + equivalent `git log --raw`. We have nominated the command for + removal, have changed the command to refuse to work unless the + `--i-still-use-this` option is given, and asked the users to report + when they do so. ++ +The command will be removed. + +* Support for `core.commentString=auto` has been deprecated and will + be removed in Git 3.0. ++ +cf. + +* Support for `core.preferSymlinkRefs=true` has been deprecated and will be + removed in Git 3.0. Writing symbolic refs as symbolic links will be phased + out in favor of using plain files using the textual representation of + symbolic refs. ++ +Symbolic references were initially always stored as a symbolic link. This was +changed in 9b143c6e15 (Teach update-ref about a symbolic ref stored in a +textfile., 2005-09-25), where a new textual symref format was introduced to +store those symbolic refs in a plain file. In 9f0bb90d16 +(core.prefersymlinkrefs: use symlinks for .git/HEAD, 2006-05-02), the Git +project switched the default to use the textual symrefs in favor of symbolic +links. ++ +The migration away from symbolic links has happened almost 20 years ago by now, +and there is no known reason why one should prefer them nowadays. Furthermore, +symbolic links are not supported on some platforms. ++ +Note that only the writing side for such symbolic links is deprecated. Reading +such symbolic links is still supported for now. + +== Superseded features that will not be deprecated + +Some features have gained newer replacements that aim to improve the design in +certain ways. The fact that there is a replacement does not automatically mean +that the old way of doing things will eventually be removed. This section tracks +those features with newer alternatives. + +* The features git-checkout(1) offers are covered by the pair of commands + git-restore(1) and git-switch(1). Because the use of git-checkout(1) is still + widespread, and it is not expected that this will change anytime soon, all + three commands will stay. ++ +This decision may get revisited in case we ever figure out that there are +almost no users of any of the commands anymore. ++ +Cf. , +, +<112b6568912a6de6672bf5592c3a718e@manjaro.org>. diff --git a/BreakingChanges.html b/BreakingChanges.html new file mode 100644 index 000000000..cc3d9d5c8 --- /dev/null +++ b/BreakingChanges.html @@ -0,0 +1,940 @@ + + + + + + + +Upcoming breaking changes + + + + + + +
+
+
+
+

The Git project aims to ensure backwards compatibility to the best extent +possible. Minor releases will not break backwards compatibility unless there is +a very strong reason to do so, like for example a security vulnerability.

+
+
+

Regardless of that, due to the age of the Git project, it is only natural to +accumulate a backlog of backwards-incompatible changes that will eventually be +required to keep the project aligned with a changing world. These changes fall +into several categories:

+
+
+
    +
  • +

    Changes to long established defaults.

    +
  • +
  • +

    Concepts that have been replaced with a superior design.

    +
  • +
  • +

    Concepts, commands, configuration or options that have been lacking in major +ways and that cannot be fixed and which will thus be removed without any +replacement.

    +
  • +
+
+
+

Explicitly not included in this list are fixes to minor bugs that may cause a +change in user-visible behavior.

+
+
+

The Git project irregularly releases breaking versions that deliberately break +backwards compatibility with older versions. This is done to ensure that Git +remains relevant, safe and maintainable going forward. The release cadence of +breaking versions is typically measured in multiple years. We had the following +major breaking releases in the past:

+
+
+
    +
  • +

    Git 1.6.0, released in August 2008.

    +
  • +
  • +

    Git 2.0, released in May 2014.

    +
  • +
+
+
+

We use <major>.<minor> release numbers these days, starting from Git 2.0. For +future releases, our plan is to increment <major> in the release number when we +make the next breaking release. Before Git 2.0, the release numbers were +1.<major>.<minor> with the intention to increment <major> for "usual" breaking +releases, reserving the jump to Git 2.0 for really large backward-compatibility +breaking changes.

+
+
+

The intent of this document is to track upcoming deprecations for future +breaking releases. Furthermore, this document also tracks what will not be +deprecated. This is done such that the outcome of discussions document both +when the discussion favors deprecation, but also when it rejects a deprecation.

+
+
+

Items should have a clear summary of the reasons why we do or do not want to +make the described change that can be easily understood without having to read +the mailing list discussions. If there are alternatives to the changed feature, +those alternatives should be pointed out to our users.

+
+
+

All items should be accompanied by references to relevant mailing list threads +where the deprecation was discussed. These references use message-IDs, which +can visited via

+
+
+
+
https://lore.kernel.org/git/$message_id/
+
+
+
+

to see the message and its surrounding discussion. Such a reference is there to +make it easier for you to find how the project reached consensus on the +described item back then.

+
+
+

This is a living document as the environment surrounding the project changes +over time. If circumstances change, an earlier decision to deprecate or change +something may need to be revisited from time to time. So do not take items on +this list to mean "it is settled, do not waste our time bringing it up again".

+
+
+
+
+

Procedure

+
+
+

Discussing the desire to make breaking changes, declaring that breaking +changes are made at a certain version boundary, and recording these +decisions in this document, are necessary but not sufficient. +Because such changes are expected to be numerous, and the design and +implementation of them are expected to span over time, they have to +be deployable trivially at such a version boundary, prepared over long +time.

+
+
+

The breaking changes MUST be guarded with the a compile-time switch, +WITH_BREAKING_CHANGES, to help this process. When built with it, +the resulting Git binary together with its documentation would +behave as if these breaking changes slated for the next big version +boundary are already in effect. We also have a CI job to exercise +the work-in-progress version of Git with these breaking changes.

+
+
+
+
+

Git 3.0

+
+
+

The following subsections document upcoming breaking changes for Git 3.0. There +is no planned release date for this breaking version yet.

+
+
+

Proposed changes and removals only include items which are "ready" to be done. +In other words, this is not supposed to be a wishlist of features that should +be changed to or replaced in case the alternative was implemented already.

+
+
+

Changes

+
+
    +
  • +

    The default hash function for new repositories will be changed from "sha1" +to "sha256". SHA-1 has been deprecated by NIST in 2011 and is nowadays +recommended against in FIPS 140-2 and similar certifications. Furthermore, +there are practical attacks on SHA-1 that weaken its cryptographic properties:

    +
    +
      +
    • +

      The SHAppening (2015). The first demonstration of a practical attack +against SHA-1 with 2^57 operations.

      +
    • +
    • +

      SHAttered (2017). Generation of two valid PDF files with 2^63 operations.

      +
    • +
    • +

      Birthday-Near-Collision (2019). This attack allows for chosen prefix +attacks with 2^68 operations.

      +
    • +
    • +

      Shambles (2020). This attack allows for chosen prefix attacks with 2^63 +operations.

      +
      +

      While we have protections in place against known attacks, it is expected +that more attacks against SHA-1 will be found by future research. Paired +with the ever-growing capability of hardware, it is only a matter of time +before SHA-1 will be considered broken completely. We want to be prepared +and will thus change the default hash algorithm to "sha256" for newly +initialized repositories.

      +
      +
      +

      An important requirement for this change is that the ecosystem is ready to +support the "sha256" object format. This includes popular Git libraries, +applications and forges.

      +
      +
      +

      There is no plan to deprecate the "sha1" object format at this point in time.

      +
      +
      +

      Cf. <2f5de416-04ba-c23d-1e0b-83bb655829a7@zombino.com>, +<20170223155046.e7nxivfwqqoprsqj@LykOS.localdomain>, +<CA+EOSBncr=4a4d8n9xS4FNehyebpmX8JiUwCsXD47EQDE+DiUQ@mail.gmail.com>.

      +
      +
    • +
    +
    +
  • +
  • +

    The default storage format for references in newly created repositories will +be changed from "files" to "reftable". The "reftable" format provides +multiple advantages over the "files" format:

    +
    +
      +
    • +

      It is impossible to store two references that only differ in casing on +case-insensitive filesystems with the "files" format. This issue is common +on Windows and macOS platforms. As the "reftable" backend does not use +filesystem paths to encode reference names this problem goes away.

      +
    • +
    • +

      Similarly, macOS normalizes path names that contain unicode characters, +which has the consequence that you cannot store two names with unicode +characters that are encoded differently with the "files" backend. Again, +this is not an issue with the "reftable" backend.

      +
    • +
    • +

      Deleting references with the "files" backend requires Git to rewrite the +complete "packed-refs" file. In large repositories with many references +this file can easily be dozens of megabytes in size, in extreme cases it +may be gigabytes. The "reftable" backend uses tombstone markers for +deleted references and thus does not have to rewrite all of its data.

      +
    • +
    • +

      Repository housekeeping with the "files" backend typically performs +all-into-one repacks of references. This can be quite expensive, and +consequently housekeeping is a tradeoff between the number of loose +references that accumulate and slow down operations that read references, +and compressing those loose references into the "packed-refs" file. The +"reftable" backend uses geometric compaction after every write, which +amortizes costs and ensures that the backend is always in a +well-maintained state.

      +
    • +
    • +

      Operations that write multiple references at once are not atomic with the +"files" backend. Consequently, Git may see in-between states when it reads +references while a reference transaction is in the process of being +committed to disk.

      +
    • +
    • +

      Writing many references at once is slow with the "files" backend because +every reference is created as a separate file. The "reftable" backend +significantly outperforms the "files" backend by multiple orders of +magnitude.

      +
    • +
    • +

      The reftable backend uses a binary format with prefix compression for +reference names. As a result, the format uses less space compared to the +"packed-refs" file.

      +
      +

      Users that get immediate benefit from the "reftable" backend could continue to +opt-in to the "reftable" format manually by setting the "init.defaultRefFormat" +config. But defaults matter, and we think that overall users will have a better +experience with less platform-specific quirks when they use the new backend by +default.

      +
      +
      +

      A prerequisite for this change is that the ecosystem is ready to support the +"reftable" format. Most importantly, alternative implementations of Git like +JGit, libgit2 and Gitoxide need to support it.

      +
      +
    • +
    +
    +
  • +
  • +

    In new repositories, the default branch name will be main. We have been +warning that the default name will change since 675704c74dd (init: +provide useful advice about init.defaultBranch, 2020-12-11). The new name +matches the default branch name used in new repositories by many of the +big Git forges.

    +
  • +
  • +

    Git will require Rust as a mandatory part of the build process. While Git +already started to adopt Rust in Git 2.49, all parts written in Rust are +optional for the time being. This includes:

    +
    +
      +
    • +

      The Rust wrapper around libgit.a that is part of "contrib/" and which has +been introduced in Git 2.49.

      +
    • +
    • +

      Subsystems that have an alternative implementation in Rust to test +interoperability between our C and Rust codebase.

      +
    • +
    • +

      Newly written features that are not mission critical for a fully functional +Git client.

      +
      +

      These changes are meant as test balloons to allow distributors of Git to prepare +for Rust becoming a mandatory part of the build process. There will be multiple +milestones for the introduction of Rust:

      +
      +
      +
      +
      +
        +
      1. +

        Initially, with Git 2.52, support for Rust will be auto-detected by Meson and +disabled in our Makefile so that the project can sort out the initial +infrastructure.

        +
      2. +
      3. +

        In Git 2.53, both build systems will default-enable support for Rust. +Consequently, builds will break by default if Rust is not available on the +build host. The use of Rust can still be explicitly disabled via build +flags.

        +
      4. +
      5. +

        In Git 3.0, the build options will be removed and support for Rust is +mandatory.

        +
      6. +
      +
      +
      +
      +
      +

      You can explicitly ask both Meson and our Makefile-based system to enable Rust +by saying meson configure -Drust=enabled and make WITH_RUST=YesPlease, +respectively.

      +
      +
      +

      The Git project will declare the last version before Git 3.0 to be a long-term +support release. This long-term release will receive important bug fixes for at +least four release cycles and security fixes for six release cycles. The Git +project will hand over maintainership of the long-term release to distributors +in case they need to extend the life of that long-term release even further. +Details of how this long-term release will be handed over to the community will +be discussed once the Git project decides to stop officially supporting it.

      +
      +
      +

      We will evaluate the impact on downstream distributions before making Rust +mandatory in Git 3.0. If we see that the impact on downstream distributions +would be significant, we may decide to defer this change to a subsequent minor +release. This evaluation will also take into account our own experience with +how painful it is to keep Rust an optional component.

      +
      +
    • +
    +
    +
  • +
+
+
+
+

Removals

+
+
    +
  • +

    Support for grafting commits has long been superseded by git-replace(1). +Grafts are inferior to replacement refs:

    +
    +
      +
    • +

      Grafts are a local-only mechanism and cannot be shared across +repositories.

      +
    • +
    • +

      Grafts can lead to hard-to-diagnose problems when transferring objects +between repositories.

      +
      +

      The grafting mechanism has been marked as outdated since e650d0643b (docs: mark +info/grafts as outdated, 2014-03-05) and will be removed.

      +
      + +
    • +
    +
    +
  • +
  • +

    The git-pack-redundant(1) command can be used to remove redundant pack files. +The subcommand is unusably slow and the reason why nobody reports it as a +performance bug is suspected to be the absence of users. We have nominated +the command for removal and have started to emit a user-visible warning in +c3b58472be (pack-redundant: gauge the usage before proposing its removal, +2020-08-25) whenever the command is executed.

    +
    +

    So far there was a single complaint about somebody still using the command, but +that complaint did not cause us to reverse course. On the contrary, we have +doubled down on the deprecation and starting with 4406522b76 (pack-redundant: +escalate deprecation warning to an error, 2023-03-23), the command dies unless +the user passes the --i-still-use-this option.

    +
    +
    +

    There have not been any subsequent complaints, so this command will finally be +removed.

    +
    + +
  • +
  • +

    Support for storing shorthands for remote URLs in "$GIT_COMMON_DIR/branches/" +and "$GIT_COMMON_DIR/remotes/" has been long superseded by storing remotes in +the repository configuration.

    +
    +

    The mechanism has originally been introduced in f170e4b39d ([PATCH] fetch/pull: +short-hand notation for remote repositories., 2005-07-16) and was superseded by +6687f8fea2 ([PATCH] Use .git/remote/origin, not .git/branches/origin., +2005-08-20), where we switched from ".git/branches/" to ".git/remotes/". That +commit already mentions an upcoming deprecation of the ".git/branches/" +directory, and starting with a1d4aa7424 (Add repository-layout document., +2005-09-01) we have also marked this layout as deprecated. Eventually we also +started to migrate away from ".git/remotes/" in favor of config-based remotes, +and we have marked the directory as legacy in 3d3d282146 (Documentation: +Grammar correction, wording fixes and cleanup, 2011-08-23)

    +
    +
    +

    As our documentation mentions, these directories are unlikely to be used in +modern repositories and most users aren’t even aware of these mechanisms. They +have been deprecated for almost 20 years and 14 years respectively, and we are +not aware of any active users that have complained about this deprecation. +Furthermore, the ".git/branches/" directory is nowadays misleadingly named and +may cause confusion as "branches" are almost exclusively used in the context of +references.

    +
    +
    +

    These features will be removed.

    +
    +
  • +
  • +

    Support for "--stdin" option in the "name-rev" command was +deprecated (and hidden from the documentation) in the Git 2.40 +timeframe, in preference to its synonym "--annotate-stdin". Git 3.0 +removes the support for "--stdin" altogether.

    +
  • +
  • +

    The git-whatchanged(1) command has outlived its usefulness more than +10 years ago, and takes more keystrokes to type than its rough +equivalent git log --raw. We have nominated the command for +removal, have changed the command to refuse to work unless the +--i-still-use-this option is given, and asked the users to report +when they do so.

    +
    +

    The command will be removed.

    +
    +
  • +
  • +

    Support for core.commentString=auto has been deprecated and will +be removed in Git 3.0.

    +
    +

    cf. <xmqqa59i45wc.fsf@gitster.g>

    +
    +
  • +
  • +

    Support for core.preferSymlinkRefs=true has been deprecated and will be +removed in Git 3.0. Writing symbolic refs as symbolic links will be phased +out in favor of using plain files using the textual representation of +symbolic refs.

    +
    +

    Symbolic references were initially always stored as a symbolic link. This was +changed in 9b143c6e15 (Teach update-ref about a symbolic ref stored in a +textfile., 2005-09-25), where a new textual symref format was introduced to +store those symbolic refs in a plain file. In 9f0bb90d16 +(core.prefersymlinkrefs: use symlinks for .git/HEAD, 2006-05-02), the Git +project switched the default to use the textual symrefs in favor of symbolic +links.

    +
    +
    +

    The migration away from symbolic links has happened almost 20 years ago by now, +and there is no known reason why one should prefer them nowadays. Furthermore, +symbolic links are not supported on some platforms.

    +
    +
    +

    Note that only the writing side for such symbolic links is deprecated. Reading +such symbolic links is still supported for now.

    +
    +
  • +
+
+
+
+
+
+

Superseded features that will not be deprecated

+
+
+

Some features have gained newer replacements that aim to improve the design in +certain ways. The fact that there is a replacement does not automatically mean +that the old way of doing things will eventually be removed. This section tracks +those features with newer alternatives.

+
+
+
    +
  • +

    The features git-checkout(1) offers are covered by the pair of commands +git-restore(1) and git-switch(1). Because the use of git-checkout(1) is still +widespread, and it is not expected that this will change anytime soon, all +three commands will stay.

    +
    +

    This decision may get revisited in case we ever figure out that there are +almost no users of any of the commands anymore.

    +
    +
    +

    Cf. <xmqqttjazwwa.fsf@gitster.g>, +<xmqqleeubork.fsf@gitster.g>, +<112b6568912a6de6672bf5592c3a718e@manjaro.org>.

    +
    +
  • +
+
+
+
+
+ + + \ No newline at end of file diff --git a/DecisionMaking.adoc b/DecisionMaking.adoc new file mode 100644 index 000000000..b43c472ae --- /dev/null +++ b/DecisionMaking.adoc @@ -0,0 +1,74 @@ +Decision-Making Process in the Git Project +========================================== + +Introduction +------------ +This document describes the current decision-making process in the Git +project. It is a descriptive rather than prescriptive doc; that is, we want to +describe how things work in practice rather than explicitly recommending any +particular process or changes to the current process. + +Here we document how the project makes decisions for discussions +(with or without patches), in scale larger than an individual patch +series (which is fully covered by the SubmittingPatches document). + + +Larger Discussions (with patches) +--------------------------------- +As with discussions on an individual patch series, starting a larger-scale +discussion often begins by sending a patch or series to the list. This might +take the form of an initial design doc, with implementation following in later +iterations of the series (for example, +link:https://lore.kernel.org/git/0169ce6fb9ccafc089b74ae406db0d1a8ff8ac65.1688165272.git.steadmon@google.com/[adding unit tests] or +link:https://lore.kernel.org/git/20200420235310.94493-1-emilyshaffer@google.com/[config-based hooks]), +or it might include a full implementation from the beginning. +In either case, discussion progresses the same way for an individual patch series, +until consensus is reached or the topic is dropped. + + +Larger Discussions (without patches) +------------------------------------ +Occasionally, larger discussions might occur without an associated patch series. +These may be very large-scale technical decisions that are beyond the scope of +even a single large patch series, or they may be more open-ended, +policy-oriented discussions (examples: +link:https://lore.kernel.org/git/ZZ77NQkSuiRxRDwt@nand.local/[introducing Rust] +or link:https://lore.kernel.org/git/YHofmWcIAidkvJiD@google.com/[improving submodule UX]). +In either case, discussion progresses as described above for general patch series. + +For larger discussions without a patch series or other concrete implementation, +it may be hard to judge when consensus has been reached, as there are not any +official guidelines. If discussion stalls at this point, it may be helpful to +restart discussion with an RFC patch series (such as a partial, unfinished +implementation or proof of concept) that can be more easily debated. + +When consensus is reached that it is a good idea, the original +proposer is expected to coordinate the effort to make it happen, +with help from others who were involved in the discussion, as +needed. + +For decisions that require code changes, it is often the case that the original +proposer will follow up with a patch series, although it is also common for +other interested parties to provide an implementation (or parts of the +implementation, for very large changes). + +For non-technical decisions such as community norms or processes, it is up to +the community as a whole to implement and sustain agreed-upon changes. +The project leadership committee (PLC) may help the implementation of +policy decisions. + + +Other Discussion Venues +----------------------- +Occasionally decision proposals are presented off-list, e.g. at the semi-regular +Contributors' Summit. While higher-bandwidth face-to-face discussion is often +useful for quickly reaching consensus among attendees, generally we expect to +summarize the discussion in notes that can later be presented on-list. For an +example, see the thread +link:https://lore.kernel.org/git/AC2EB721-2979-43FD-922D-C5076A57F24B@jramsay.com.au/[Notes +from Git Contributor Summit, Los Angeles (April 5, 2020)] by James Ramsay. + +We prefer that "official" discussion happens on the list so that the full +community has opportunity to engage in discussion. This also means that the +mailing list archives contain a more-or-less complete history of project +discussions and decisions. diff --git a/DecisionMaking.html b/DecisionMaking.html new file mode 100644 index 000000000..9d7ba783c --- /dev/null +++ b/DecisionMaking.html @@ -0,0 +1,545 @@ + + + + + + + +Decision-Making Process in the Git Project + + + + + + +
+
+

Introduction

+
+
+

This document describes the current decision-making process in the Git +project. It is a descriptive rather than prescriptive doc; that is, we want to +describe how things work in practice rather than explicitly recommending any +particular process or changes to the current process.

+
+
+

Here we document how the project makes decisions for discussions +(with or without patches), in scale larger than an individual patch +series (which is fully covered by the SubmittingPatches document).

+
+
+
+
+

Larger Discussions (with patches)

+
+
+

As with discussions on an individual patch series, starting a larger-scale +discussion often begins by sending a patch or series to the list. This might +take the form of an initial design doc, with implementation following in later +iterations of the series (for example, +adding unit tests or +config-based hooks), +or it might include a full implementation from the beginning. +In either case, discussion progresses the same way for an individual patch series, +until consensus is reached or the topic is dropped.

+
+
+
+
+

Larger Discussions (without patches)

+
+
+

Occasionally, larger discussions might occur without an associated patch series. +These may be very large-scale technical decisions that are beyond the scope of +even a single large patch series, or they may be more open-ended, +policy-oriented discussions (examples: +introducing Rust +or improving submodule UX). +In either case, discussion progresses as described above for general patch series.

+
+
+

For larger discussions without a patch series or other concrete implementation, +it may be hard to judge when consensus has been reached, as there are not any +official guidelines. If discussion stalls at this point, it may be helpful to +restart discussion with an RFC patch series (such as a partial, unfinished +implementation or proof of concept) that can be more easily debated.

+
+
+

When consensus is reached that it is a good idea, the original +proposer is expected to coordinate the effort to make it happen, +with help from others who were involved in the discussion, as +needed.

+
+
+

For decisions that require code changes, it is often the case that the original +proposer will follow up with a patch series, although it is also common for +other interested parties to provide an implementation (or parts of the +implementation, for very large changes).

+
+
+

For non-technical decisions such as community norms or processes, it is up to +the community as a whole to implement and sustain agreed-upon changes. +The project leadership committee (PLC) may help the implementation of +policy decisions.

+
+
+
+
+

Other Discussion Venues

+
+
+

Occasionally decision proposals are presented off-list, e.g. at the semi-regular +Contributors' Summit. While higher-bandwidth face-to-face discussion is often +useful for quickly reaching consensus among attendees, generally we expect to +summarize the discussion in notes that can later be presented on-list. For an +example, see the thread +Notes +from Git Contributor Summit, Los Angeles (April 5, 2020) by James Ramsay.

+
+
+

We prefer that "official" discussion happens on the list so that the full +community has opportunity to engage in discussion. This also means that the +mailing list archives contain a more-or-less complete history of project +discussions and decisions.

+
+
+
+
+ + + \ No newline at end of file diff --git a/MyFirstContribution.adoc b/MyFirstContribution.adoc new file mode 100644 index 000000000..f186dfbc8 --- /dev/null +++ b/MyFirstContribution.adoc @@ -0,0 +1,1424 @@ +My First Contribution to the Git Project +======================================== +:sectanchors: + +[[summary]] +== Summary + +This is a tutorial demonstrating the end-to-end workflow of creating a change to +the Git tree, sending it for review, and making changes based on comments. + +[[prerequisites]] +=== Prerequisites + +This tutorial assumes you're already fairly familiar with using Git to manage +source code. The Git workflow steps will largely remain unexplained. + +[[related-reading]] +=== Related Reading + +This tutorial aims to summarize the following documents, but the reader may find +useful additional context: + +- `Documentation/SubmittingPatches` +- `Documentation/howto/new-command.adoc` + +[[getting-help]] +=== Getting Help + +If you get stuck, you can seek help in the following places. + +==== git@vger.kernel.org + +This is the main Git project mailing list where code reviews, version +announcements, design discussions, and more take place. Those interested in +contributing are welcome to post questions here. The Git list requires +plain-text-only emails and prefers inline and bottom-posting when replying to +mail; you will be CC'd in all replies to you. Optionally, you can subscribe to +the list by sending an email to +(see https://subspace.kernel.org/subscribing.html for details). +The https://lore.kernel.org/git[archive] of this mailing list is +available to view in a browser. + +==== https://web.libera.chat/#git-devel[#git-devel] on Libera Chat + +This IRC channel is for conversations between Git contributors. If someone is +currently online and knows the answer to your question, you can receive help +in real time. Otherwise, you can read the +https://colabti.org/irclogger/irclogger_logs/git-devel[scrollback] to see +whether someone answered you. IRC does not allow offline private messaging, so +if you try to private message someone and then log out of IRC, they cannot +respond to you. It's better to ask your questions in the channel so that you +can be answered if you disconnect and so that others can learn from the +conversation. + +==== https://discord.gg/GRFVkzgxRd[#discord] on Discord +This is an unofficial Git Discord server for everyone, from people just +starting out with Git to those who develop it. It's a great place to ask +questions, share tips, and connect with the broader Git community in real time. + +The server has channels for general discussions and specific channels for those +who use Git and those who develop it. The server's search functionality also +allows you to find previous conversations and answers to common questions. + +[[getting-started]] +== Getting Started + +[[cloning]] +=== Clone the Git Repository + +Git is mirrored in a number of locations. Clone the repository from one of them; +https://git-scm.com/downloads suggests one of the best places to clone from is +the mirror on GitHub. + +---- +$ git clone https://github.com/git/git git +$ cd git +---- + +[[dependencies]] +=== Installing Dependencies + +To build Git from source, you need to have a handful of dependencies installed +on your system. For a hint of what's needed, you can take a look at +`INSTALL`, paying close attention to the section about Git's dependencies on +external programs and libraries. That document mentions a way to "test-drive" +our freshly built Git without installing; that's the method we'll be using in +this tutorial. + +Make sure that your environment has everything you need by building your brand +new clone of Git from the above step: + +---- +$ make +---- + +NOTE: The Git build is parallelizable. `-j#` is not included above but you can +use it as you prefer, here and elsewhere. + +[[identify-problem]] +=== Identify Problem to Solve + +//// +Use + to indicate fixed-width here; couldn't get ` to work nicely with the +quotes around "Pony Saying 'Um, Hello'". +//// +In this tutorial, we will add a new command, +git psuh+, short for ``Pony Saying +`Um, Hello''' - a feature which has gone unimplemented despite a high frequency +of invocation during users' typical daily workflow. + +(We've seen some other effort in this space with the implementation of popular +commands such as `sl`.) + +[[setup-workspace]] +=== Set Up Your Workspace + +Let's start by making a development branch to work on our changes. Per +`Documentation/SubmittingPatches`, since a brand new command is a new feature, +it's fine to base your work on `master`. However, in the future for bugfixes, +etc., you should check that document and base it on the appropriate branch. + +For the purposes of this document, we will base all our work on the `master` +branch of the upstream project. Create the `psuh` branch you will use for +development like so: + +---- +$ git checkout -b psuh origin/master +---- + +We'll make a number of commits here in order to demonstrate how to send a topic +with multiple patches up for review simultaneously. + +[[code-it-up]] +== Code It Up! + +NOTE: A reference implementation can be found at +https://github.com/nasamuffin/git/tree/psuh. + +[[add-new-command]] +=== Adding a New Command + +Lots of the subcommands are written as builtins, which means they are +implemented in C and compiled into the main `git` executable. Implementing the +very simple `psuh` command as a built-in will demonstrate the structure of the +codebase, the internal API, and the process of working together as a contributor +with the reviewers and maintainer to integrate this change into the system. + +Built-in subcommands are typically implemented in a function named "cmd_" +followed by the name of the subcommand, in a source file named after the +subcommand and contained within `builtin/`. So it makes sense to implement your +command in `builtin/psuh.c`. Create that file, and within it, write the entry +point for your command in a function matching the style and signature: + +---- +int cmd_psuh(int argc UNUSED, const char **argv UNUSED, + const char *prefix UNUSED, struct repository *repo UNUSED) +---- + +A few things to note: + +* A subcommand implementation takes its command line arguments + in `int argc` + `const char **argv`, like `main()` would. + +* It also takes two extra parameters, `prefix` and `repo`. What + they mean will not be discussed until much later. + +* Because this first example will not use any of the parameters, + your compiler will give warnings on unused parameters. As the + list of these four parameters is mandated by the API to add + new built-in commands, you cannot omit them. Instead, you add + `UNUSED` to each of them to tell the compiler that you *know* + you are not (yet) using it. + +We'll also need to add the declaration of psuh; open up `builtin.h`, find the +declaration for `cmd_pull`, and add a new line for `psuh` immediately before it, +in order to keep the declarations alphabetically sorted: + +---- +int cmd_psuh(int argc, const char **argv, const char *prefix, struct repository *repo); +---- + +Be sure to `#include "builtin.h"` in your `psuh.c`. You'll also need to +`#include "gettext.h"` to use functions related to printing output text. + +Go ahead and add some throwaway printf to the `cmd_psuh` function. This is a +decent starting point as we can now add build rules and register the command. + +NOTE: Your throwaway text, as well as much of the text you will be adding over +the course of this tutorial, is user-facing. That means it needs to be +localizable. Take a look at `po/README` under "Marking strings for translation". +Throughout the tutorial, we will mark strings for translation as necessary; you +should also do so when writing your user-facing commands in the future. + +---- +int cmd_psuh(int argc UNUSED, const char **argv UNUSED, + const char *prefix UNUSED, struct repository *repo UNUSED) +{ + printf(_("Pony saying hello goes here.\n")); + return 0; +} +---- + +Let's try to build it. Open `Makefile`, find where `builtin/pull.o` is added +to `BUILTIN_OBJS`, and add `builtin/psuh.o` in the same way next to it in +alphabetical order. Once you've done so, move to the top-level directory and +build simply with `make`. Also add the `DEVELOPER=1` variable to turn on +some additional warnings: + +---- +$ echo DEVELOPER=1 >config.mak +$ make +---- + +NOTE: When you are developing the Git project, it's preferred that you use the +`DEVELOPER` flag; if there's some reason it doesn't work for you, you can turn +it off, but it's a good idea to mention the problem to the mailing list. + +Great, now your new command builds happily on its own. But nobody invokes it. +Let's change that. + +The list of commands lives in `git.c`. We can register a new command by adding +a `cmd_struct` to the `commands[]` array. `struct cmd_struct` takes a string +with the command name, a function pointer to the command implementation, and a +setup option flag. For now, let's keep mimicking `push`. Find the line where +`cmd_push` is registered, copy it, and modify it for `cmd_psuh`, placing the new +line in alphabetical order (immediately before `cmd_pull`). + +The options are documented in `builtin.h` under "Adding a new built-in." Since +we hope to print some data about the user's current workspace context later, +we need a Git directory, so choose `RUN_SETUP` as your only option. + +Go ahead and build again. You should see a clean build, so let's kick the tires +and see if it works. There's a binary you can use to test with in the +`bin-wrappers` directory. + +---- +$ ./bin-wrappers/git psuh +---- + +Check it out! You've got a command! Nice work! Let's commit this. + +`git status` reveals modified `Makefile`, `builtin.h`, and `git.c` as well as +untracked `builtin/psuh.c` and `git-psuh`. First, let's take care of the binary, +which should be ignored. Open `.gitignore` in your editor, find `/git-pull`, and +add an entry for your new command in alphabetical order: + +---- +... +/git-prune-packed +/git-psuh +/git-pull +/git-push +/git-quiltimport +/git-range-diff +... +---- + +Checking `git status` again should show that `git-psuh` has been removed from +the untracked list and `.gitignore` has been added to the modified list. Now we +can stage and commit: + +---- +$ git add Makefile builtin.h builtin/psuh.c git.c .gitignore +$ git commit -s +---- + +You will be presented with your editor in order to write a commit message. Start +the commit with a 50-column or less subject line, including the name of the +component you're working on, followed by a blank line (always required) and then +the body of your commit message, which should provide the bulk of the context. +Remember to be explicit and provide the "Why" of your change, especially if it +couldn't easily be understood from your diff. When editing your commit message, +don't remove the `Signed-off-by` trailer which was added by `-s` above. + +---- +psuh: add a built-in by popular demand + +Internal metrics indicate this is a command many users expect to be +present. So here's an implementation to help drive customer +satisfaction and engagement: a pony which doubtfully greets the user, +or, a Pony Saying "Um, Hello" (PSUH). + +This commit message is intentionally formatted to 72 columns per line, +starts with a single line as "commit message subject" that is written as +if to command the codebase to do something (add this, teach a command +that). The body of the message is designed to add information about the +commit that is not readily deduced from reading the associated diff, +such as answering the question "why?". + +Signed-off-by: A U Thor +---- + +Go ahead and inspect your new commit with `git show`. "psuh:" indicates you +have modified mainly the `psuh` command. The subject line gives readers an idea +of what you've changed. The sign-off line (`-s`) indicates that you agree to +the Developer's Certificate of Origin 1.1 (see the +`Documentation/SubmittingPatches` +++[[dco]]+++ header). + +For the remainder of the tutorial, the subject line only will be listed for the +sake of brevity. However, fully-fleshed example commit messages are available +on the reference implementation linked at the top of this document. + +[[implementation]] +=== Implementation + +It's probably useful to do at least something besides printing out a string. +Let's start by having a look at everything we get. + +Modify your `cmd_psuh` implementation to dump the args you're passed, +keeping existing `printf()` calls in place; because the args are now +used, remove the `UNUSED` macro from them: + +---- + int i; + + ... + + printf(Q_("Your args (there is %d):\n", + "Your args (there are %d):\n", + argc), + argc); + for (i = 0; i < argc; i++) + printf("%d: %s\n", i, argv[i]); + + printf(_("Your current working directory:\n%s%s\n"), + prefix ? "/" : "", prefix ? prefix : ""); + +---- + +Build and try it. As you may expect, there's pretty much just whatever we give +on the command line, including the name of our command. (If `prefix` is empty +for you, try `cd Documentation/ && ../bin-wrappers/git psuh`). That's not so +helpful. So what other context can we get? + +Add a line to `#include "config.h"` and `#include "repository.h"`. +Then, add the following bits to the function body: +function body: + +---- + const char *cfg_name; + +... + + repo_config(repo, git_default_config, NULL); + if (repo_config_get_string_tmp(repo, "user.name", &cfg_name)) + printf(_("No name is found in config\n")); + else + printf(_("Your name: %s\n"), cfg_name); +---- + +`repo_config()` will grab the configuration from config files known to Git and +apply standard precedence rules. `repo_config_get_string_tmp()` will look up +a specific key ("user.name") and give you the value. There are a number of +single-key lookup functions like this one; you can see them all (and more info +about how to use `repo_config()`) in `Documentation/technical/api-config.adoc`. + +You should see that the name printed matches the one you see when you run: + +---- +$ git config --get user.name +---- + +Great! Now we know how to check for values in the Git config. Let's commit this +too, so we don't lose our progress. + +---- +$ git add builtin/psuh.c +$ git commit -sm "psuh: show parameters & config opts" +---- + +NOTE: Again, the above is for sake of brevity in this tutorial. In a real change +you should not use `-m` but instead use the editor to write a meaningful +message. + +Still, it'd be nice to know what the user's working context is like. Let's see +if we can print the name of the user's current branch. We can mimic the +`git status` implementation; the printer is located in `wt-status.c` and we can +see that the branch is held in a `struct wt_status`. + +`wt_status_print()` gets invoked by `cmd_status()` in `builtin/commit.c`. +Looking at that implementation we see the status config being populated like so: + +---- +status_init_config(&s, git_status_config); +---- + +But as we drill down, we can find that `status_init_config()` wraps a call +to `repo_config()`. Let's modify the code we wrote in the previous commit. + +Be sure to include the header to allow you to use `struct wt_status`: + +---- +#include "wt-status.h" +---- + +Then modify your `cmd_psuh` implementation to declare your `struct wt_status`, +prepare it, and print its contents: + +---- + struct wt_status status; + +... + + wt_status_prepare(repo, &status); + repo_config(repo, git_default_config, &status); + +... + + printf(_("Your current branch: %s\n"), status.branch); +---- + +Run it again. Check it out - here's the (verbose) name of your current branch! + +Let's commit this as well. + +---- +$ git add builtin/psuh.c +$ git commit -sm "psuh: print the current branch" +---- + +Now let's see if we can get some info about a specific commit. + +Luckily, there are some helpers for us here. `commit.h` has a function called +`lookup_commit_reference_by_name` to which we can simply provide a hardcoded +string; `pretty.h` has an extremely handy `pp_commit_easy()` call which doesn't +require a full format object to be passed. + +Add the following includes: + +---- +#include "commit.h" +#include "pretty.h" +---- + +Then, add the following lines within your implementation of `cmd_psuh()` near +the declarations and the logic, respectively. + +---- + struct commit *c = NULL; + struct strbuf commitline = STRBUF_INIT; + +... + + c = lookup_commit_reference_by_name("origin/master"); + + if (c != NULL) { + pp_commit_easy(CMIT_FMT_ONELINE, c, &commitline); + printf(_("Current commit: %s\n"), commitline.buf); + } +---- + +The `struct strbuf` provides some safety belts to your basic `char*`, one of +which is a length member to prevent buffer overruns. It needs to be initialized +nicely with `STRBUF_INIT`. Keep it in mind when you need to pass around `char*`. + +`lookup_commit_reference_by_name` resolves the name you pass it, so you can play +with the value there and see what kind of things you can come up with. + +`pp_commit_easy` is a convenience wrapper in `pretty.h` that takes a single +format enum shorthand, rather than an entire format struct. It then +pretty-prints the commit according to that shorthand. These are similar to the +formats available with `--pretty=FOO` in many Git commands. + +Build it and run, and if you're using the same name in the example, you should +see the subject line of the most recent commit in `origin/master` that you know +about. Neat! Let's commit that as well. + +---- +$ git add builtin/psuh.c +$ git commit -sm "psuh: display the top of origin/master" +---- + +[[add-documentation]] +=== Adding Documentation + +Awesome! You've got a fantastic new command that you're ready to share with the +community. But hang on just a minute - this isn't very user-friendly. Run the +following: + +---- +$ ./bin-wrappers/git help psuh +---- + +Your new command is undocumented! Let's fix that. + +Take a look at `Documentation/git-*.adoc`. These are the manpages for the +subcommands that Git knows about. You can open these up and take a look to get +acquainted with the format, but then go ahead and make a new file +`Documentation/git-psuh.adoc`. Like with most of the documentation in the Git +project, help pages are written with AsciiDoc (see CodingGuidelines, "Writing +Documentation" section). Use the following template to fill out your own +manpage: + +// Surprisingly difficult to embed AsciiDoc source within AsciiDoc. +[listing] +.... +git-psuh(1) +=========== + +NAME +---- +git-psuh - Delight users' typo with a shy horse + + +SYNOPSIS +-------- +[verse] +'git-psuh [...]' + +DESCRIPTION +----------- +... + +OPTIONS[[OPTIONS]] +------------------ +... + +OUTPUT +------ +... + +GIT +--- +Part of the linkgit:git[1] suite +.... + +The most important pieces of this to note are the file header, underlined by =, +the NAME section, and the SYNOPSIS, which would normally contain the grammar if +your command took arguments. Try to use well-established manpage headers so your +documentation is consistent with other Git and UNIX manpages; this makes life +easier for your user, who can skip to the section they know contains the +information they need. + +NOTE: Before trying to build the docs, make sure you have the package `asciidoc` +installed. + +Now that you've written your manpage, you'll need to build it explicitly. We +convert your AsciiDoc to troff which is man-readable like so: + +---- +$ make all doc +$ man Documentation/git-psuh.1 +---- + +or + +---- +$ make -C Documentation/ git-psuh.1 +$ man Documentation/git-psuh.1 +---- + +While this isn't as satisfying as running through `git help`, you can at least +check that your help page looks right. + +You can also check that the documentation coverage is good (that is, the project +sees that your command has been implemented as well as documented) by running +`make check-docs` from the top-level. + +Go ahead and commit your new documentation change. + +[[add-usage]] +=== Adding Usage Text + +Try and run `./bin-wrappers/git psuh -h`. Your command should crash at the end. +That's because `-h` is a special case which your command should handle by +printing usage. + +Take a look at `Documentation/technical/api-parse-options.adoc`. This is a handy +tool for pulling out options you need to be able to handle, and it takes a +usage string. + +In order to use it, we'll need to prepare a NULL-terminated array of usage +strings and a `builtin_psuh_options` array. + +Add a line to `#include "parse-options.h"`. + +At global scope, add your array of usage strings: + +---- +static const char * const psuh_usage[] = { + N_("git psuh [...]"), + NULL, +}; +---- + +Then, within your `cmd_psuh()` implementation, we can declare and populate our +`option` struct. Ours is pretty boring but you can add more to it if you want to +explore `parse_options()` in more detail: + +---- + struct option options[] = { + OPT_END() + }; +---- + +Finally, before you print your args and prefix, add the call to +`parse-options()`: + +---- + argc = parse_options(argc, argv, prefix, options, psuh_usage, 0); +---- + +This call will modify your `argv` parameter. It will strip the options you +specified in `options` from `argv` and the locations pointed to from `options` +entries will be updated. Be sure to replace your `argc` with the result from +`parse_options()`, or you will be confused if you try to parse `argv` later. + +It's worth noting the special argument `--`. As you may be aware, many Unix +commands use `--` to indicate "end of named parameters" - all parameters after +the `--` are interpreted merely as positional arguments. (This can be handy if +you want to pass as a parameter something which would usually be interpreted as +a flag.) `parse_options()` will terminate parsing when it reaches `--` and give +you the rest of the options afterwards, untouched. + +Now that you have a usage hint, you can teach Git how to show it in the general +command list shown by `git help git` or `git help -a`, which is generated from +`command-list.txt`. Find the line for 'git-pull' so you can add your 'git-psuh' +line above it in alphabetical order. Now, we can add some attributes about the +command which impacts where it shows up in the aforementioned help commands. The +top of `command-list.txt` shares some information about what each attribute +means; in those help pages, the commands are sorted according to these +attributes. `git psuh` is user-facing, or porcelain - so we will mark it as +"mainporcelain". For "mainporcelain" commands, the comments at the top of +`command-list.txt` indicate we can also optionally add an attribute from another +list; since `git psuh` shows some information about the user's workspace but +doesn't modify anything, let's mark it as "info". Make sure to keep your +attributes in the same style as the rest of `command-list.txt` using spaces to +align and delineate them: + +---- +git-prune-packed plumbingmanipulators +git-psuh mainporcelain info +git-pull mainporcelain remote +git-push mainporcelain remote +---- + +Build again. Now, when you run with `-h`, you should see your usage printed and +your command terminated before anything else interesting happens. Great! + +Go ahead and commit this one, too. + +[[testing]] +== Testing + +It's important to test your code - even for a little toy command like this one. +Moreover, your patch won't be accepted into the Git tree without tests. Your +tests should: + +* Illustrate the current behavior of the feature +* Prove the current behavior matches the expected behavior +* Ensure the externally-visible behavior isn't broken in later changes + +So let's write some tests. + +Related reading: `t/README` + +[[overview-test-structure]] +=== Overview of Testing Structure + +The tests in Git live in `t/` and are named with a 4-digit decimal number using +the schema shown in the Naming Tests section of `t/README`. + +[[write-new-test]] +=== Writing Your Test + +Since this a toy command, let's go ahead and name the test with t9999. However, +as many of the family/subcmd combinations are full, best practice seems to be +to find a command close enough to the one you've added and share its naming +space. + +Create a new file `t/t9999-psuh-tutorial.sh`. Begin with the header as so (see +"Writing Tests" and "Source 'test-lib.sh'" in `t/README`): + +---- +#!/bin/sh + +test_description='git-psuh test + +This test runs git-psuh and makes sure it does not crash.' + +. ./test-lib.sh +---- + +Tests are framed inside of a `test_expect_success` in order to output TAP +formatted results. Let's make sure that `git psuh` doesn't exit poorly and does +mention the right animal somewhere: + +---- +test_expect_success 'runs correctly with no args and good output' ' + git psuh >actual && + grep Pony actual +' +---- + +Indicate that you've run everything you wanted by adding the following at the +bottom of your script: + +---- +test_done +---- + +Make sure you mark your test script executable: + +---- +$ chmod +x t/t9999-psuh-tutorial.sh +---- + +You can get an idea of whether you created your new test script successfully +by running `make -C t test-lint`, which will check for things like test number +uniqueness, executable bit, and so on. + +[[local-test]] +=== Running Locally + +Let's try and run locally: + +---- +$ make +$ cd t/ && prove t9999-psuh-tutorial.sh +---- + +You can run the full test suite and ensure `git-psuh` didn't break anything: + +---- +$ cd t/ +$ prove -j$(nproc) --shuffle t[0-9]*.sh +---- + +NOTE: You can also do this with `make test` or use any testing harness which can +speak TAP. `prove` can run concurrently. `shuffle` randomizes the order the +tests are run in, which makes them resilient against unwanted inter-test +dependencies. `prove` also makes the output nicer. + +Go ahead and commit this change, as well. + +[[ready-to-share]] +== Getting Ready to Share: Anatomy of a Patch Series + +You may have noticed already that the Git project performs its code reviews via +emailed patches, which are then applied by the maintainer when they are ready +and approved by the community. The Git project does not accept contributions from +pull requests, and the patches emailed for review need to be formatted a +specific way. + +:patch-series: https://lore.kernel.org/git/pull.1218.git.git.1645209647.gitgitgadget@gmail.com/ +:lore: https://lore.kernel.org/git/ + +Before taking a look at how to convert your commits into emailed patches, +let's analyze what the end result, a "patch series", looks like. Here is an +{patch-series}[example] of the summary view for a patch series on the web interface of +the {lore}[Git mailing list archive]: + +---- +2022-02-18 18:40 [PATCH 0/3] libify reflog John Cai via GitGitGadget +2022-02-18 18:40 ` [PATCH 1/3] reflog: libify delete reflog function and helpers John Cai via GitGitGadget +2022-02-18 19:10 ` Ævar Arnfjörð Bjarmason [this message] +2022-02-18 19:39 ` Taylor Blau +2022-02-18 19:48 ` Ævar Arnfjörð Bjarmason +2022-02-18 19:35 ` Taylor Blau +2022-02-21 1:43 ` John Cai +2022-02-21 1:50 ` Taylor Blau +2022-02-23 19:50 ` John Cai +2022-02-18 20:00 ` // other replies elided +2022-02-18 18:40 ` [PATCH 2/3] reflog: call reflog_delete from reflog.c John Cai via GitGitGadget +2022-02-18 19:15 ` Ævar Arnfjörð Bjarmason +2022-02-18 20:26 ` Junio C Hamano +2022-02-18 18:40 ` [PATCH 3/3] stash: call reflog_delete from reflog.c John Cai via GitGitGadget +2022-02-18 19:20 ` Ævar Arnfjörð Bjarmason +2022-02-19 0:21 ` Taylor Blau +2022-02-22 2:36 ` John Cai +2022-02-22 10:51 ` Ævar Arnfjörð Bjarmason +2022-02-18 19:29 ` [PATCH 0/3] libify reflog Ævar Arnfjörð Bjarmason +2022-02-22 18:30 ` [PATCH v2 0/3] libify reflog John Cai via GitGitGadget +2022-02-22 18:30 ` [PATCH v2 1/3] stash: add test to ensure reflog --rewrite --updatref behavior John Cai via GitGitGadget +2022-02-23 8:54 ` Ævar Arnfjörð Bjarmason +2022-02-23 21:27 ` Junio C Hamano +// continued +---- + +We can note a few things: + +- Each commit is sent as a separate email, with the commit message title as + subject, prefixed with "[PATCH _i_/_n_]" for the _i_-th commit of an + _n_-commit series. +- Each patch is sent as a reply to an introductory email called the _cover + letter_ of the series, prefixed "[PATCH 0/_n_]". +- Subsequent iterations of the patch series are labelled "PATCH v2", "PATCH + v3", etc. in place of "PATCH". For example, "[PATCH v2 1/3]" would be the first of + three patches in the second iteration. Each iteration is sent with a new cover + letter (like "[PATCH v2 0/3]" above), itself a reply to the cover letter of the + previous iteration (more on that below). + +NOTE: A single-patch topic is sent with "[PATCH]", "[PATCH v2]", etc. without +_i_/_n_ numbering (in the above thread overview, no single-patch topic appears, +though). + +[[cover-letter]] +=== The cover letter + +In addition to an email per patch, the Git community also expects your patches +to come with a cover letter. This is an important component of change +submission as it explains to the community from a high level what you're trying +to do, and why, in a way that's more apparent than just looking at your +patches. + +The title of your cover letter should be something which succinctly covers the +purpose of your entire topic branch. It's often in the imperative mood, just +like our commit message titles. Here is how we'll title our series: + +--- +Add the 'psuh' command +--- + +The body of the cover letter is used to give additional context to reviewers. +Be sure to explain anything your patches don't make clear on their own, but +remember that since the cover letter is not recorded in the commit history, +anything that might be useful to future readers of the repository's history +should also be in your commit messages. + +Here's an example body for `psuh`: + +---- +Our internal metrics indicate widespread interest in the command +git-psuh - that is, many users are trying to use it, but finding it is +unavailable, using some unknown workaround instead. + +The following handful of patches add the psuh command and implement some +handy features on top of it. + +This patchset is part of the MyFirstContribution tutorial and should not +be merged. +---- + +At this point the tutorial diverges, in order to demonstrate two +different methods of formatting your patchset and getting it reviewed. + +The first method to be covered is GitGitGadget, which is useful for those +already familiar with GitHub's common pull request workflow. This method +requires a GitHub account. + +The second method to be covered is `git send-email`, which can give slightly +more fine-grained control over the emails to be sent. This method requires some +setup which can change depending on your system and will not be covered in this +tutorial. + +Regardless of which method you choose, your engagement with reviewers will be +the same; the review process will be covered after the sections on GitGitGadget +and `git send-email`. + +[[howto-ggg]] +== Sending Patches via GitGitGadget + +One option for sending patches is to follow a typical pull request workflow and +send your patches out via GitGitGadget. GitGitGadget is a tool created by +Johannes Schindelin to make life as a Git contributor easier for those used to +the GitHub PR workflow. It allows contributors to open pull requests against its +mirror of the Git project, and does some magic to turn the PR into a set of +emails and send them out for you. It also runs the Git continuous integration +suite for you. It's documented at https://gitgitgadget.github.io/. + +[[create-fork]] +=== Forking `git/git` on GitHub + +Before you can send your patch off to be reviewed using GitGitGadget, you will +need to fork the Git project and upload your changes. First thing - make sure +you have a GitHub account. + +Head to the https://github.com/git/git[GitHub mirror] and look for the Fork +button. Place your fork wherever you deem appropriate and create it. + +[[upload-to-fork]] +=== Uploading to Your Own Fork + +To upload your branch to your own fork, you'll need to add the new fork as a +remote. You can use `git remote -v` to show the remotes you have added already. +From your new fork's page on GitHub, you can press "Clone or download" to get +the URL; then you need to run the following to add, replacing your own URL and +remote name for the examples provided: + +---- +$ git remote add remotename git@github.com:remotename/git.git +---- + +or to use the HTTPS URL: + +---- +$ git remote add remotename https://github.com/remotename/git/.git +---- + +Run `git remote -v` again and you should see the new remote showing up. +`git fetch remotename` (with the real name of your remote replaced) in order to +get ready to push. + +Next, double-check that you've been doing all your development in a new branch +by running `git branch`. If you didn't, now is a good time to move your new +commits to their own branch. + +As mentioned briefly at the beginning of this document, we are basing our work +on `master`, so go ahead and update as shown below, or using your preferred +workflow. + +---- +$ git checkout master +$ git pull -r +$ git rebase master psuh +---- + +Finally, you're ready to push your new topic branch! (Due to our branch and +command name choices, be careful when you type the command below.) + +---- +$ git push remotename psuh +---- + +Now you should be able to go and check out your newly created branch on GitHub. + +[[send-pr-ggg]] +=== Sending a PR to GitGitGadget + +In order to have your code tested and formatted for review, you need to start by +opening a Pull Request against either `gitgitgadget/git` or `git/git`. Head to +https://github.com/gitgitgadget/git or https://github.com/git/git and open a PR +either with the "New pull request" button or the convenient "Compare & pull +request" button that may appear with the name of your newly pushed branch. + +The differences between using `gitgitgadget/git` and `git/git` as your base can +be found [here](https://gitgitgadget.github.io/#should-i-use-gitgitgadget-on-gitgitgadgets-git-fork-or-on-gits-github-mirror) + +Review the PR's title and description, as they're used by GitGitGadget +respectively as the subject and body of the cover letter for your change. Refer +to <> above for advice on how to title your +submission and what content to include in the description. + +NOTE: For single-patch contributions, your commit message should already be +meaningful and explain at a high level the purpose (what is happening and why) +of your patch, so you usually do not need any additional context. In that case, +remove the PR description that GitHub automatically generates from your commit +message (your PR description should be empty). If you do need to supply even +more context, you can do so in that space and it will be appended to the email +that GitGitGadget will send, between the three-dash line and the diffstat +(see <> for how this looks once +submitted). + +When you're happy, submit your pull request. + +[[run-ci-ggg]] +=== Running CI and Getting Ready to Send + +If it's your first time using GitGitGadget (which is likely, as you're using +this tutorial) then someone will need to give you permission to use the tool. +As mentioned in the GitGitGadget documentation, you just need someone who +already uses it to comment on your PR with `/allow `. GitGitGadget +will automatically run your PRs through the CI even without the permission given +but you will not be able to `/submit` your changes until someone allows you to +use the tool. + +NOTE: You can typically find someone who can `/allow` you on GitGitGadget by +either examining recent pull requests where someone has been granted `/allow` +(https://github.com/gitgitgadget/git/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+%22%2Fallow%22[Search: +is:pr is:open "/allow"]), in which case both the author and the person who +granted the `/allow` can now `/allow` you, or by inquiring on the +https://web.libera.chat/#git-devel[#git-devel] IRC channel on Libera Chat +linking your pull request and asking for someone to `/allow` you. + +If the CI fails, you can update your changes with `git rebase -i` and push your +branch again: + +---- +$ git push -f remotename psuh +---- + +In fact, you should continue to make changes this way up until the point when +your patch is accepted into `next`. + +//// +TODO https://github.com/gitgitgadget/gitgitgadget/issues/83 +It'd be nice to be able to verify that the patch looks good before sending it +to everyone on Git mailing list. +[[check-work-ggg]] +=== Check Your Work +//// + +[[send-mail-ggg]] +=== Sending Your Patches + +Now that your CI is passing and someone has granted you permission to use +GitGitGadget with the `/allow` command, sending out for review is as simple as +commenting on your PR with `/submit`. + +[[responding-ggg]] +=== Updating With Comments + +Skip ahead to <> for information on how to +reply to review comments you will receive on the mailing list. + +Once you have your branch again in the shape you want following all review +comments, you can submit again: + +---- +$ git push -f remotename psuh +---- + +Next, go look at your pull request against GitGitGadget; you should see the CI +has been kicked off again. Now while the CI is running is a good time for you +to modify your description at the top of the pull request thread; it will be +used again as the cover letter. You should use this space to describe what +has changed since your previous version, so that your reviewers have some idea +of what they're looking at. When the CI is done running, you can comment once +more with `/submit` - GitGitGadget will automatically add a v2 mark to your +changes. + +[[howto-git-send-email]] +== Sending Patches with `git send-email` + +If you don't want to use GitGitGadget, you can also use Git itself to mail your +patches. Some benefits of using Git this way include finer grained control of +subject line (for example, being able to use the tag [RFC PATCH] in the subject) +and being able to send a ``dry run'' mail to yourself to ensure it all looks +good before going out to the list. + +[[setup-git-send-email]] +=== Prerequisite: Setting Up `git send-email` + +Configuration for `send-email` can vary based on your operating system and email +provider, and so will not be covered in this tutorial, beyond stating that in +many distributions of Linux, `git-send-email` is not packaged alongside the +typical `git` install. You may need to install this additional package; there +are a number of resources online to help you do so. You will also need to +determine the right way to configure it to use your SMTP server; again, as this +configuration can change significantly based on your system and email setup, it +is out of scope for the context of this tutorial. + +[[format-patch]] +=== Preparing Initial Patchset + +Sending emails with Git is a two-part process; before you can prepare the emails +themselves, you'll need to prepare the patches. Luckily, this is pretty simple: + +---- +$ git format-patch --cover-letter -o psuh/ --base=auto psuh@{u}..psuh +---- + + . The `--cover-letter` option tells `format-patch` to create a + cover letter template for you. You will need to fill in the + template before you're ready to send - but for now, the template + will be next to your other patches. + + . The `-o psuh/` option tells `format-patch` to place the patch + files into a directory. This is useful because `git send-email` + can take a directory and send out all the patches from there. + + . The `--base=auto` option tells the command to record the "base + commit", on which the recipient is expected to apply the patch + series. The `auto` value will cause `format-patch` to compute + the base commit automatically, which is the merge base of tip + commit of the remote-tracking branch and the specified revision + range. + + . The `psuh@{u}..psuh` option tells `format-patch` to generate + patches for the commits you created on the `psuh` branch since it + forked from its upstream (which is `origin/master` if you + followed the example in the "Set up your workspace" section). If + you are already on the `psuh` branch, you can just say `@{u}`, + which means "commits on the current branch since it forked from + its upstream", which is the same thing. + +The command will make one patch file per commit. After you +run, you can go have a look at each of the patches with your favorite text +editor and make sure everything looks alright; however, it's not recommended to +make code fixups via the patch file. It's a better idea to make the change the +normal way using `git rebase -i` or by adding a new commit than by modifying a +patch. + +NOTE: Optionally, you can also use the `--rfc` flag to prefix your patch subject +with ``[RFC PATCH]'' instead of ``[PATCH]''. RFC stands for ``request for +comments'' and indicates that while your code isn't quite ready for submission, +you'd like to begin the code review process. This can also be used when your +patch is a proposal, but you aren't sure whether the community wants to solve +the problem with that approach or not - to conduct a sort of design review. You +may also see on the list patches marked ``WIP'' - this means they are incomplete +but want reviewers to look at what they have so far. You can add this flag with +`--subject-prefix=WIP`. + +Check and make sure that your patches and cover letter template exist in the +directory you specified - you're nearly ready to send out your review! + +[[preparing-cover-letter]] +=== Preparing Email + +Since you invoked `format-patch` with `--cover-letter`, you've already got a +cover letter template ready. Open it up in your favorite editor. + +You should see a number of headers present already. Check that your `From:` +header is correct. Then modify your `Subject:` (see <> for +how to choose good title for your patch series): + +---- +Subject: [PATCH 0/7] Add the 'psuh' command +---- + +Make sure you retain the ``[PATCH 0/X]'' part; that's what indicates to the Git +community that this email is the beginning of a patch series, and many +reviewers filter their email for this type of flag. + +You'll need to add some extra parameters when you invoke `git send-email` to add +the cover letter. + +Next you'll have to fill out the body of your cover letter. Again, see +<> for what content to include. + +The template created by `git format-patch --cover-letter` includes a diffstat. +This gives reviewers a summary of what they're in for when reviewing your topic. +The one generated for `psuh` from the sample implementation looks like this: + +---- + Documentation/git-psuh.adoc | 40 +++++++++++++++++++++ + Makefile | 1 + + builtin.h | 1 + + builtin/psuh.c | 73 ++++++++++++++++++++++++++++++++++++++ + git.c | 1 + + t/t9999-psuh-tutorial.sh | 12 +++++++ + 6 files changed, 128 insertions(+) + create mode 100644 Documentation/git-psuh.adoc + create mode 100644 builtin/psuh.c + create mode 100755 t/t9999-psuh-tutorial.sh +---- + +Finally, the letter will include the version of Git used to generate the +patches. You can leave that string alone. + +[[sending-git-send-email]] +=== Sending Email + +At this point you should have a directory `psuh/` which is filled with your +patches and a cover letter. Time to mail it out! You can send it like this: + +---- +$ git send-email --to=target@example.com psuh/*.patch +---- + +NOTE: Check `git help send-email` for some other options which you may find +valuable, such as changing the Reply-to address or adding more CC and BCC lines. + +:contrib-scripts: footnoteref:[contrib-scripts,Scripts under `contrib/` are + +not part of the core `git` binary and must be called directly. Clone the Git + +codebase and run `perl contrib/contacts/git-contacts`.] + +NOTE: If you're not sure whom to CC, running `contrib/contacts/git-contacts` can +list potential reviewers. In addition, you can do `git send-email +--cc-cmd='perl contrib/contacts/git-contacts' feature/*.patch`{contrib-scripts} to +automatically pass this list of emails to `send-email`. + +NOTE: When you are sending a real patch, it will go to git@vger.kernel.org - but +please don't send your patchset from the tutorial to the real mailing list! For +now, you can send it to yourself, to make sure you understand how it will look. + +NOTE: After sending your patches, you can confirm that they reached the mailing +list by visiting https://lore.kernel.org/git/. Use the search bar to find your +name or the subject of your patch. If it appears, your email was successfully +delivered. + +After you run the command above, you will be presented with an interactive +prompt for each patch that's about to go out. This gives you one last chance to +edit or quit sending something (but again, don't edit code this way). Once you +press `y` or `a` at these prompts your emails will be sent! Congratulations! + +Awesome, now the community will drop everything and review your changes. (Just +kidding - be patient!) + +[[v2-git-send-email]] +=== Sending v2 + +This section will focus on how to send a v2 of your patchset. To learn what +should go into v2, skip ahead to <> for +information on how to handle comments from reviewers. + +We'll reuse our `psuh` topic branch for v2. Before we make any changes, we'll +mark the tip of our v1 branch for easy reference: + +---- +$ git checkout psuh +$ git branch psuh-v1 +---- + +Refine your patch series by using `git rebase -i` to adjust commits based upon +reviewer comments. Once the patch series is ready for submission, generate your +patches again, but with some new flags: + +---- +$ git format-patch -v2 --cover-letter -o psuh/ --range-diff master..psuh-v1 master.. +---- + +The `--range-diff master..psuh-v1` parameter tells `format-patch` to include a +range-diff between `psuh-v1` and `psuh` in the cover letter (see +linkgit:git-range-diff[1]). This helps tell reviewers about the differences +between your v1 and v2 patches. + +The `-v2` parameter tells `format-patch` to output your patches +as version "2". For instance, you may notice that your v2 patches are +all named like `v2-000n-my-commit-subject.patch`. `-v2` will also format +your patches by prefixing them with "[PATCH v2]" instead of "[PATCH]", +and your range-diff will be prefaced with "Range-diff against v1". + +After you run this command, `format-patch` will output the patches to the `psuh/` +directory, alongside the v1 patches. Using a single directory makes it easy to +refer to the old v1 patches while proofreading the v2 patches, but you will need +to be careful to send out only the v2 patches. We will use a pattern like +`psuh/v2-*.patch` (not `psuh/*.patch`, which would match v1 and v2 patches). + +Edit your cover letter again. Now is a good time to mention what's different +between your last version and now, if it's something significant. You do not +need the exact same body in your second cover letter; focus on explaining to +reviewers the changes you've made that may not be as visible. + +You will also need to go and find the Message-ID of your previous cover letter. +You can either note it when you send the first series, from the output of `git +send-email`, or you can look it up on the +https://lore.kernel.org/git[mailing list]. Find your cover letter in the +archives, click on it, then click "permalink" or "raw" to reveal the Message-ID +header. It should match: + +---- +Message-ID: +---- + +Your Message-ID is ``. This example will be used +below as well; make sure to replace it with the correct Message-ID for your +**previous cover letter** - that is, if you're sending v2, use the Message-ID +from v1; if you're sending v3, use the Message-ID from v2. + +While you're looking at the email, you should also note who is CC'd, as it's +common practice in the mailing list to keep all CCs on a thread. You can add +these CC lines directly to your cover letter with a line like so in the header +(before the Subject line): + +---- +CC: author@example.com, Othe R +---- + +Now send the emails again, paying close attention to which messages you pass in +to the command: + +---- +$ git send-email --to=target@example.com + --in-reply-to="" + psuh/v2-*.patch +---- + +[[single-patch]] +=== Bonus Chapter: One-Patch Changes + +In some cases, your very small change may consist of only one patch. When that +happens, you only need to send one email. Your commit message should already be +meaningful and explain at a high level the purpose (what is happening and why) +of your patch, but if you need to supply even more context, you can do so below +the `---` in your patch. Take the example below, which was generated with `git +format-patch` on a single commit, and then edited to add the content between +the `---` and the diffstat. + +---- +From 1345bbb3f7ac74abde040c12e737204689a72723 Mon Sep 17 00:00:00 2001 +From: A U Thor +Date: Thu, 18 Apr 2019 15:11:02 -0700 +Subject: [PATCH] README: change the grammar + +I think it looks better this way. This part of the commit message will +end up in the commit-log. + +Signed-off-by: A U Thor +--- +Let's have a wild discussion about grammar on the mailing list. This +part of my email will never end up in the commit log. Here is where I +can add additional context to the mailing list about my intent, outside +of the context of the commit log. This section was added after `git +format-patch` was run, by editing the patch file in a text editor. + + README.md | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/README.md b/README.md +index 88f126184c..38da593a60 100644 +--- a/README.md ++++ b/README.md +@@ -3,7 +3,7 @@ + Git - fast, scalable, distributed revision control system + ========================================================= + +-Git is a fast, scalable, distributed revision control system with an ++Git is a fast, scalable, and distributed revision control system with an + unusually rich command set that provides both high-level operations + and full access to internals. + +-- +2.21.0.392.gf8f6787159e-goog +---- + +[[now-what]] +== My Patch Got Emailed - Now What? + +Please give reviewers enough time to process your initial patch before +sending an updated version. That is, resist the temptation to send a new +version immediately, because others may have already started reviewing +your initial version. + +While waiting for review comments, you may find mistakes in your initial +patch, or perhaps realize a different and better way to achieve the goal +of the patch. In this case you may communicate your findings to other +reviewers as follows: + + - If the mistakes you found are minor, send a reply to your patch as if + you were a reviewer and mention that you will fix them in an + updated version. + + - On the other hand, if you think you want to change the course so + drastically that reviews on the initial patch would be a waste of + time (for everyone involved), retract the patch immediately with + a reply like "I am working on a much better approach, so please + ignore this patch and wait for the updated version." + +Now, the above is a good practice if you sent your initial patch +prematurely without polish. But a better approach of course is to avoid +sending your patch prematurely in the first place. + +Please be considerate of the time needed by reviewers to examine each +new version of your patch. Rather than seeing the initial version right +now (followed by several "oops, I like this version better than the +previous one" patches over 2 days), reviewers would strongly prefer if a +single polished version came 2 days later instead, and that version with +fewer mistakes were the only one they would need to review. + + +[[reviewing]] +=== Responding to Reviews + +After a few days, you will hopefully receive a reply to your patchset with some +comments. Woohoo! Now you can get back to work. + +It's good manners to reply to each comment, notifying the reviewer that you have +made the change suggested, feel the original is better, or that the comment +inspired you to do something a new way which is superior to both the original +and the suggested change. This way reviewers don't need to inspect your v2 to +figure out whether you implemented their comment or not. + +Reviewers may ask you about what you wrote in the patchset, either in +the proposed commit log message or in the changes themselves. You +should answer these questions in your response messages, but often the +reason why reviewers asked these questions to understand what you meant +to write is because your patchset needed clarification to be understood. + +Do not be satisfied by just answering their questions in your response +and hear them say that they now understand what you wanted to say. +Update your patches to clarify the points reviewers had trouble with, +and prepare your v2; the words you used to explain your v1 to answer +reviewers' questions may be useful thing to use. Your goal is to make +your v2 clear enough so that it becomes unnecessary for you to give the +same explanation to the next person who reads it. + +If you are going to push back on a comment, be polite and explain why you feel +your original is better; be prepared that the reviewer may still disagree with +you, and the rest of the community may weigh in on one side or the other. As +with all code reviews, it's important to keep an open mind to doing something a +different way than you originally planned; other reviewers have a different +perspective on the project than you do, and may be thinking of a valid side +effect which had not occurred to you. It is always okay to ask for clarification +if you aren't sure why a change was suggested, or what the reviewer is asking +you to do. + +Make sure your email client has a plaintext email mode and it is turned on; the +Git list rejects HTML email. Please also follow the mailing list etiquette +outlined in the +https://kernel.googlesource.com/pub/scm/git/git/+/todo/MaintNotes[Maintainer's +Note], which are similar to etiquette rules in most open source communities +surrounding bottom-posting and inline replies. + +When you're making changes to your code, it is cleanest - that is, the resulting +commits are easiest to look at - if you use `git rebase -i` (interactive +rebase). Take a look at this +https://www.oreilly.com/library/view/git-pocket-guide/9781449327507/ch10.html[overview] +from O'Reilly. The general idea is to modify each commit which requires changes; +this way, instead of having a patch A with a mistake, a patch B which was fine +and required no upstream reviews in v1, and a patch C which fixes patch A for +v2, you can just ship a v2 with a correct patch A and correct patch B. This is +changing history, but since it's local history which you haven't shared with +anyone, that is okay for now! (Later, it may not make sense to do this; take a +look at the section below this one for some context.) + +[[after-approval]] +=== After Review Approval + +The Git project has four integration branches: `seen`, `next`, `master`, and +`maint`. Your change will be placed into `seen` fairly early on by the maintainer +while it is still in the review process; from there, when it is ready for wider +testing, it will be merged into `next`. Plenty of early testers use `next` and +may report issues. Eventually, changes in `next` will make it to `master`, +which is typically considered stable. Finally, when a new release is cut, +`maint` is used to base bugfixes onto. As mentioned at the beginning of this +document, you can read `Documents/SubmittingPatches` for some more info about +the use of the various integration branches. + +Back to now: your code has been lauded by the upstream reviewers. It is perfect. +It is ready to be accepted. You don't need to do anything else; the maintainer +will merge your topic branch to `next` and life is good. + +However, if you discover it isn't so perfect after this point, you may need to +take some special steps depending on where you are in the process. + +If the maintainer has announced in the "What's cooking in git.git" email that +your topic is marked for `next` - that is, that they plan to merge it to `next` +but have not yet done so - you should send an email asking the maintainer to +wait a little longer: "I've sent v4 of my series and you marked it for `next`, +but I need to change this and that - please wait for v5 before you merge it." + +If the topic has already been merged to `next`, rather than modifying your +patches with `git rebase -i`, you should make further changes incrementally - +that is, with another commit, based on top of the maintainer's topic branch as +detailed in https://github.com/gitster/git. Your work is still in the same topic +but is now incremental, rather than a wholesale rewrite of the topic branch. + +The topic branches in the maintainer's GitHub are mirrored in GitGitGadget, so +if you're sending your reviews out that way, you should be sure to open your PR +against the appropriate GitGitGadget/Git branch. + +If you're using `git send-email`, you can use it the same way as before, but you +should generate your diffs from `..` and base your work on +`` instead of `master`. diff --git a/MyFirstContribution.html b/MyFirstContribution.html new file mode 100644 index 000000000..935e0294e --- /dev/null +++ b/MyFirstContribution.html @@ -0,0 +1,2295 @@ + + + + + + + +My First Contribution to the Git Project + + + + + + +
+
+

Summary

+
+
+

This is a tutorial demonstrating the end-to-end workflow of creating a change to +the Git tree, sending it for review, and making changes based on comments.

+
+
+

Prerequisites

+
+

This tutorial assumes you’re already fairly familiar with using Git to manage +source code. The Git workflow steps will largely remain unexplained.

+
+
+
+ +
+

This tutorial aims to summarize the following documents, but the reader may find +useful additional context:

+
+
+
    +
  • +

    Documentation/SubmittingPatches

    +
  • +
  • +

    Documentation/howto/new-command.adoc

    +
  • +
+
+
+
+

Getting Help

+
+

If you get stuck, you can seek help in the following places.

+
+
+

git@vger.kernel.org

+
+

This is the main Git project mailing list where code reviews, version +announcements, design discussions, and more take place. Those interested in +contributing are welcome to post questions here. The Git list requires +plain-text-only emails and prefers inline and bottom-posting when replying to +mail; you will be CC’d in all replies to you. Optionally, you can subscribe to +the list by sending an email to <git+subscribe@vger.kernel.org> +(see https://subspace.kernel.org/subscribing.html for details). +The archive of this mailing list is +available to view in a browser.

+
+
+
+

#git-devel on Libera Chat

+
+

This IRC channel is for conversations between Git contributors. If someone is +currently online and knows the answer to your question, you can receive help +in real time. Otherwise, you can read the +scrollback to see +whether someone answered you. IRC does not allow offline private messaging, so +if you try to private message someone and then log out of IRC, they cannot +respond to you. It’s better to ask your questions in the channel so that you +can be answered if you disconnect and so that others can learn from the +conversation.

+
+
+
+

#discord on Discord

+
+

This is an unofficial Git Discord server for everyone, from people just +starting out with Git to those who develop it. It’s a great place to ask +questions, share tips, and connect with the broader Git community in real time.

+
+
+

The server has channels for general discussions and specific channels for those +who use Git and those who develop it. The server’s search functionality also +allows you to find previous conversations and answers to common questions.

+
+
+
+
+
+
+

Getting Started

+
+
+

Clone the Git Repository

+
+

Git is mirrored in a number of locations. Clone the repository from one of them; +https://git-scm.com/downloads suggests one of the best places to clone from is +the mirror on GitHub.

+
+
+
+
$ git clone https://github.com/git/git git
+$ cd git
+
+
+
+
+

Installing Dependencies

+
+

To build Git from source, you need to have a handful of dependencies installed +on your system. For a hint of what’s needed, you can take a look at +INSTALL, paying close attention to the section about Git’s dependencies on +external programs and libraries. That document mentions a way to "test-drive" +our freshly built Git without installing; that’s the method we’ll be using in +this tutorial.

+
+
+

Make sure that your environment has everything you need by building your brand +new clone of Git from the above step:

+
+
+
+
$ make
+
+
+
+ + + + + +
+
Note
+
+The Git build is parallelizable. -j# is not included above but you can +use it as you prefer, here and elsewhere. +
+
+
+
+

Identify Problem to Solve

+
+

In this tutorial, we will add a new command, git psuh, short for “Pony Saying +‘Um, Hello”’ - a feature which has gone unimplemented despite a high frequency +of invocation during users' typical daily workflow.

+
+
+

(We’ve seen some other effort in this space with the implementation of popular +commands such as sl.)

+
+
+
+

Set Up Your Workspace

+
+

Let’s start by making a development branch to work on our changes. Per +Documentation/SubmittingPatches, since a brand new command is a new feature, +it’s fine to base your work on master. However, in the future for bugfixes, +etc., you should check that document and base it on the appropriate branch.

+
+
+

For the purposes of this document, we will base all our work on the master +branch of the upstream project. Create the psuh branch you will use for +development like so:

+
+
+
+
$ git checkout -b psuh origin/master
+
+
+
+

We’ll make a number of commits here in order to demonstrate how to send a topic +with multiple patches up for review simultaneously.

+
+
+
+
+
+

Code It Up!

+
+
+ + + + + +
+
Note
+
+A reference implementation can be found at +https://github.com/nasamuffin/git/tree/psuh. +
+
+
+

Adding a New Command

+
+

Lots of the subcommands are written as builtins, which means they are +implemented in C and compiled into the main git executable. Implementing the +very simple psuh command as a built-in will demonstrate the structure of the +codebase, the internal API, and the process of working together as a contributor +with the reviewers and maintainer to integrate this change into the system.

+
+
+

Built-in subcommands are typically implemented in a function named "cmd_" +followed by the name of the subcommand, in a source file named after the +subcommand and contained within builtin/. So it makes sense to implement your +command in builtin/psuh.c. Create that file, and within it, write the entry +point for your command in a function matching the style and signature:

+
+
+
+
int cmd_psuh(int argc UNUSED, const char **argv UNUSED,
+             const char *prefix UNUSED, struct repository *repo UNUSED)
+
+
+
+

A few things to note:

+
+
+
    +
  • +

    A subcommand implementation takes its command line arguments +in int argc + const char **argv, like main() would.

    +
  • +
  • +

    It also takes two extra parameters, prefix and repo. What +they mean will not be discussed until much later.

    +
  • +
  • +

    Because this first example will not use any of the parameters, +your compiler will give warnings on unused parameters. As the +list of these four parameters is mandated by the API to add +new built-in commands, you cannot omit them. Instead, you add +UNUSED to each of them to tell the compiler that you know +you are not (yet) using it.

    +
  • +
+
+
+

We’ll also need to add the declaration of psuh; open up builtin.h, find the +declaration for cmd_pull, and add a new line for psuh immediately before it, +in order to keep the declarations alphabetically sorted:

+
+
+
+
int cmd_psuh(int argc, const char **argv, const char *prefix, struct repository *repo);
+
+
+
+

Be sure to #include "builtin.h" in your psuh.c. You’ll also need to +#include "gettext.h" to use functions related to printing output text.

+
+
+

Go ahead and add some throwaway printf to the cmd_psuh function. This is a +decent starting point as we can now add build rules and register the command.

+
+
+ + + + + +
+
Note
+
+Your throwaway text, as well as much of the text you will be adding over +the course of this tutorial, is user-facing. That means it needs to be +localizable. Take a look at po/README under "Marking strings for translation". +Throughout the tutorial, we will mark strings for translation as necessary; you +should also do so when writing your user-facing commands in the future. +
+
+
+
+
int cmd_psuh(int argc UNUSED, const char **argv UNUSED,
+             const char *prefix UNUSED, struct repository *repo UNUSED)
+{
+        printf(_("Pony saying hello goes here.\n"));
+        return 0;
+}
+
+
+
+

Let’s try to build it. Open Makefile, find where builtin/pull.o is added +to BUILTIN_OBJS, and add builtin/psuh.o in the same way next to it in +alphabetical order. Once you’ve done so, move to the top-level directory and +build simply with make. Also add the DEVELOPER=1 variable to turn on +some additional warnings:

+
+
+
+
$ echo DEVELOPER=1 >config.mak
+$ make
+
+
+
+ + + + + +
+
Note
+
+When you are developing the Git project, it’s preferred that you use the +DEVELOPER flag; if there’s some reason it doesn’t work for you, you can turn +it off, but it’s a good idea to mention the problem to the mailing list. +
+
+
+

Great, now your new command builds happily on its own. But nobody invokes it. +Let’s change that.

+
+
+

The list of commands lives in git.c. We can register a new command by adding +a cmd_struct to the commands[] array. struct cmd_struct takes a string +with the command name, a function pointer to the command implementation, and a +setup option flag. For now, let’s keep mimicking push. Find the line where +cmd_push is registered, copy it, and modify it for cmd_psuh, placing the new +line in alphabetical order (immediately before cmd_pull).

+
+
+

The options are documented in builtin.h under "Adding a new built-in." Since +we hope to print some data about the user’s current workspace context later, +we need a Git directory, so choose RUN_SETUP as your only option.

+
+
+

Go ahead and build again. You should see a clean build, so let’s kick the tires +and see if it works. There’s a binary you can use to test with in the +bin-wrappers directory.

+
+
+
+
$ ./bin-wrappers/git psuh
+
+
+
+

Check it out! You’ve got a command! Nice work! Let’s commit this.

+
+
+

git status reveals modified Makefile, builtin.h, and git.c as well as +untracked builtin/psuh.c and git-psuh. First, let’s take care of the binary, +which should be ignored. Open .gitignore in your editor, find /git-pull, and +add an entry for your new command in alphabetical order:

+
+
+
+
...
+/git-prune-packed
+/git-psuh
+/git-pull
+/git-push
+/git-quiltimport
+/git-range-diff
+...
+
+
+
+

Checking git status again should show that git-psuh has been removed from +the untracked list and .gitignore has been added to the modified list. Now we +can stage and commit:

+
+
+
+
$ git add Makefile builtin.h builtin/psuh.c git.c .gitignore
+$ git commit -s
+
+
+
+

You will be presented with your editor in order to write a commit message. Start +the commit with a 50-column or less subject line, including the name of the +component you’re working on, followed by a blank line (always required) and then +the body of your commit message, which should provide the bulk of the context. +Remember to be explicit and provide the "Why" of your change, especially if it +couldn’t easily be understood from your diff. When editing your commit message, +don’t remove the Signed-off-by trailer which was added by -s above.

+
+
+
+
psuh: add a built-in by popular demand
+
+Internal metrics indicate this is a command many users expect to be
+present. So here's an implementation to help drive customer
+satisfaction and engagement: a pony which doubtfully greets the user,
+or, a Pony Saying "Um, Hello" (PSUH).
+
+This commit message is intentionally formatted to 72 columns per line,
+starts with a single line as "commit message subject" that is written as
+if to command the codebase to do something (add this, teach a command
+that). The body of the message is designed to add information about the
+commit that is not readily deduced from reading the associated diff,
+such as answering the question "why?".
+
+Signed-off-by: A U Thor <author@example.com>
+
+
+
+

Go ahead and inspect your new commit with git show. "psuh:" indicates you +have modified mainly the psuh command. The subject line gives readers an idea +of what you’ve changed. The sign-off line (-s) indicates that you agree to +the Developer’s Certificate of Origin 1.1 (see the +Documentation/SubmittingPatches [[dco]] header).

+
+
+

For the remainder of the tutorial, the subject line only will be listed for the +sake of brevity. However, fully-fleshed example commit messages are available +on the reference implementation linked at the top of this document.

+
+
+
+

Implementation

+
+

It’s probably useful to do at least something besides printing out a string. +Let’s start by having a look at everything we get.

+
+
+

Modify your cmd_psuh implementation to dump the args you’re passed, +keeping existing printf() calls in place; because the args are now +used, remove the UNUSED macro from them:

+
+
+
+
        int i;
+
+        ...
+
+        printf(Q_("Your args (there is %d):\n",
+                  "Your args (there are %d):\n",
+                  argc),
+               argc);
+        for (i = 0; i < argc; i++)
+                printf("%d: %s\n", i, argv[i]);
+
+        printf(_("Your current working directory:\n<top-level>%s%s\n"),
+               prefix ? "/" : "", prefix ? prefix : "");
+
+
+
+

Build and try it. As you may expect, there’s pretty much just whatever we give +on the command line, including the name of our command. (If prefix is empty +for you, try cd Documentation/ && ../bin-wrappers/git psuh). That’s not so +helpful. So what other context can we get?

+
+
+

Add a line to #include "config.h" and #include "repository.h". +Then, add the following bits to the function body: +function body:

+
+
+
+
        const char *cfg_name;
+
+...
+
+        repo_config(repo, git_default_config, NULL);
+        if (repo_config_get_string_tmp(repo, "user.name", &cfg_name))
+                printf(_("No name is found in config\n"));
+        else
+                printf(_("Your name: %s\n"), cfg_name);
+
+
+
+

repo_config() will grab the configuration from config files known to Git and +apply standard precedence rules. repo_config_get_string_tmp() will look up +a specific key ("user.name") and give you the value. There are a number of +single-key lookup functions like this one; you can see them all (and more info +about how to use repo_config()) in Documentation/technical/api-config.adoc.

+
+
+

You should see that the name printed matches the one you see when you run:

+
+
+
+
$ git config --get user.name
+
+
+
+

Great! Now we know how to check for values in the Git config. Let’s commit this +too, so we don’t lose our progress.

+
+
+
+
$ git add builtin/psuh.c
+$ git commit -sm "psuh: show parameters & config opts"
+
+
+
+ + + + + +
+
Note
+
+Again, the above is for sake of brevity in this tutorial. In a real change +you should not use -m but instead use the editor to write a meaningful +message. +
+
+
+

Still, it’d be nice to know what the user’s working context is like. Let’s see +if we can print the name of the user’s current branch. We can mimic the +git status implementation; the printer is located in wt-status.c and we can +see that the branch is held in a struct wt_status.

+
+
+

wt_status_print() gets invoked by cmd_status() in builtin/commit.c. +Looking at that implementation we see the status config being populated like so:

+
+
+
+
status_init_config(&s, git_status_config);
+
+
+
+

But as we drill down, we can find that status_init_config() wraps a call +to repo_config(). Let’s modify the code we wrote in the previous commit.

+
+
+

Be sure to include the header to allow you to use struct wt_status:

+
+
+
+
#include "wt-status.h"
+
+
+
+

Then modify your cmd_psuh implementation to declare your struct wt_status, +prepare it, and print its contents:

+
+
+
+
        struct wt_status status;
+
+...
+
+        wt_status_prepare(repo, &status);
+        repo_config(repo, git_default_config, &status);
+
+...
+
+        printf(_("Your current branch: %s\n"), status.branch);
+
+
+
+

Run it again. Check it out - here’s the (verbose) name of your current branch!

+
+
+

Let’s commit this as well.

+
+
+
+
$ git add builtin/psuh.c
+$ git commit -sm "psuh: print the current branch"
+
+
+
+

Now let’s see if we can get some info about a specific commit.

+
+
+

Luckily, there are some helpers for us here. commit.h has a function called +lookup_commit_reference_by_name to which we can simply provide a hardcoded +string; pretty.h has an extremely handy pp_commit_easy() call which doesn’t +require a full format object to be passed.

+
+
+

Add the following includes:

+
+
+
+
#include "commit.h"
+#include "pretty.h"
+
+
+
+

Then, add the following lines within your implementation of cmd_psuh() near +the declarations and the logic, respectively.

+
+
+
+
        struct commit *c = NULL;
+        struct strbuf commitline = STRBUF_INIT;
+
+...
+
+        c = lookup_commit_reference_by_name("origin/master");
+
+        if (c != NULL) {
+                pp_commit_easy(CMIT_FMT_ONELINE, c, &commitline);
+                printf(_("Current commit: %s\n"), commitline.buf);
+        }
+
+
+
+

The struct strbuf provides some safety belts to your basic char*, one of +which is a length member to prevent buffer overruns. It needs to be initialized +nicely with STRBUF_INIT. Keep it in mind when you need to pass around char*.

+
+
+

lookup_commit_reference_by_name resolves the name you pass it, so you can play +with the value there and see what kind of things you can come up with.

+
+
+

pp_commit_easy is a convenience wrapper in pretty.h that takes a single +format enum shorthand, rather than an entire format struct. It then +pretty-prints the commit according to that shorthand. These are similar to the +formats available with --pretty=FOO in many Git commands.

+
+
+

Build it and run, and if you’re using the same name in the example, you should +see the subject line of the most recent commit in origin/master that you know +about. Neat! Let’s commit that as well.

+
+
+
+
$ git add builtin/psuh.c
+$ git commit -sm "psuh: display the top of origin/master"
+
+
+
+
+

Adding Documentation

+
+

Awesome! You’ve got a fantastic new command that you’re ready to share with the +community. But hang on just a minute - this isn’t very user-friendly. Run the +following:

+
+
+
+
$ ./bin-wrappers/git help psuh
+
+
+
+

Your new command is undocumented! Let’s fix that.

+
+
+

Take a look at Documentation/git-*.adoc. These are the manpages for the +subcommands that Git knows about. You can open these up and take a look to get +acquainted with the format, but then go ahead and make a new file +Documentation/git-psuh.adoc. Like with most of the documentation in the Git +project, help pages are written with AsciiDoc (see CodingGuidelines, "Writing +Documentation" section). Use the following template to fill out your own +manpage:

+
+
+
+
git-psuh(1)
+===========
+
+NAME
+----
+git-psuh - Delight users' typo with a shy horse
+
+
+SYNOPSIS
+--------
+[verse]
+'git-psuh [<arg>...]'
+
+DESCRIPTION
+-----------
+...
+
+OPTIONS[[OPTIONS]]
+------------------
+...
+
+OUTPUT
+------
+...
+
+GIT
+---
+Part of the linkgit:git[1] suite
+
+
+
+

The most important pieces of this to note are the file header, underlined by =, +the NAME section, and the SYNOPSIS, which would normally contain the grammar if +your command took arguments. Try to use well-established manpage headers so your +documentation is consistent with other Git and UNIX manpages; this makes life +easier for your user, who can skip to the section they know contains the +information they need.

+
+
+ + + + + +
+
Note
+
+Before trying to build the docs, make sure you have the package asciidoc +installed. +
+
+
+

Now that you’ve written your manpage, you’ll need to build it explicitly. We +convert your AsciiDoc to troff which is man-readable like so:

+
+
+
+
$ make all doc
+$ man Documentation/git-psuh.1
+
+
+
+

or

+
+
+
+
$ make -C Documentation/ git-psuh.1
+$ man Documentation/git-psuh.1
+
+
+
+

While this isn’t as satisfying as running through git help, you can at least +check that your help page looks right.

+
+
+

You can also check that the documentation coverage is good (that is, the project +sees that your command has been implemented as well as documented) by running +make check-docs from the top-level.

+
+
+

Go ahead and commit your new documentation change.

+
+
+
+

Adding Usage Text

+
+

Try and run ./bin-wrappers/git psuh -h. Your command should crash at the end. +That’s because -h is a special case which your command should handle by +printing usage.

+
+
+

Take a look at Documentation/technical/api-parse-options.adoc. This is a handy +tool for pulling out options you need to be able to handle, and it takes a +usage string.

+
+
+

In order to use it, we’ll need to prepare a NULL-terminated array of usage +strings and a builtin_psuh_options array.

+
+
+

Add a line to #include "parse-options.h".

+
+
+

At global scope, add your array of usage strings:

+
+
+
+
static const char * const psuh_usage[] = {
+        N_("git psuh [<arg>...]"),
+        NULL,
+};
+
+
+
+

Then, within your cmd_psuh() implementation, we can declare and populate our +option struct. Ours is pretty boring but you can add more to it if you want to +explore parse_options() in more detail:

+
+
+
+
        struct option options[] = {
+                OPT_END()
+        };
+
+
+
+

Finally, before you print your args and prefix, add the call to +parse-options():

+
+
+
+
        argc = parse_options(argc, argv, prefix, options, psuh_usage, 0);
+
+
+
+

This call will modify your argv parameter. It will strip the options you +specified in options from argv and the locations pointed to from options +entries will be updated. Be sure to replace your argc with the result from +parse_options(), or you will be confused if you try to parse argv later.

+
+
+

It’s worth noting the special argument --. As you may be aware, many Unix +commands use -- to indicate "end of named parameters" - all parameters after +the -- are interpreted merely as positional arguments. (This can be handy if +you want to pass as a parameter something which would usually be interpreted as +a flag.) parse_options() will terminate parsing when it reaches -- and give +you the rest of the options afterwards, untouched.

+
+
+

Now that you have a usage hint, you can teach Git how to show it in the general +command list shown by git help git or git help -a, which is generated from +command-list.txt. Find the line for git-pull so you can add your git-psuh +line above it in alphabetical order. Now, we can add some attributes about the +command which impacts where it shows up in the aforementioned help commands. The +top of command-list.txt shares some information about what each attribute +means; in those help pages, the commands are sorted according to these +attributes. git psuh is user-facing, or porcelain - so we will mark it as +"mainporcelain". For "mainporcelain" commands, the comments at the top of +command-list.txt indicate we can also optionally add an attribute from another +list; since git psuh shows some information about the user’s workspace but +doesn’t modify anything, let’s mark it as "info". Make sure to keep your +attributes in the same style as the rest of command-list.txt using spaces to +align and delineate them:

+
+
+
+
git-prune-packed                        plumbingmanipulators
+git-psuh                                mainporcelain           info
+git-pull                                mainporcelain           remote
+git-push                                mainporcelain           remote
+
+
+
+

Build again. Now, when you run with -h, you should see your usage printed and +your command terminated before anything else interesting happens. Great!

+
+
+

Go ahead and commit this one, too.

+
+
+
+
+
+

Testing

+
+
+

It’s important to test your code - even for a little toy command like this one. +Moreover, your patch won’t be accepted into the Git tree without tests. Your +tests should:

+
+
+
    +
  • +

    Illustrate the current behavior of the feature

    +
  • +
  • +

    Prove the current behavior matches the expected behavior

    +
  • +
  • +

    Ensure the externally-visible behavior isn’t broken in later changes

    +
  • +
+
+
+

So let’s write some tests.

+
+
+

Related reading: t/README

+
+
+

Overview of Testing Structure

+
+

The tests in Git live in t/ and are named with a 4-digit decimal number using +the schema shown in the Naming Tests section of t/README.

+
+
+
+

Writing Your Test

+
+

Since this a toy command, let’s go ahead and name the test with t9999. However, +as many of the family/subcmd combinations are full, best practice seems to be +to find a command close enough to the one you’ve added and share its naming +space.

+
+
+

Create a new file t/t9999-psuh-tutorial.sh. Begin with the header as so (see +"Writing Tests" and "Source test-lib.sh" in t/README):

+
+
+
+
#!/bin/sh
+
+test_description='git-psuh test
+
+This test runs git-psuh and makes sure it does not crash.'
+
+. ./test-lib.sh
+
+
+
+

Tests are framed inside of a test_expect_success in order to output TAP +formatted results. Let’s make sure that git psuh doesn’t exit poorly and does +mention the right animal somewhere:

+
+
+
+
test_expect_success 'runs correctly with no args and good output' '
+        git psuh >actual &&
+        grep Pony actual
+'
+
+
+
+

Indicate that you’ve run everything you wanted by adding the following at the +bottom of your script:

+
+
+
+
test_done
+
+
+
+

Make sure you mark your test script executable:

+
+
+
+
$ chmod +x t/t9999-psuh-tutorial.sh
+
+
+
+

You can get an idea of whether you created your new test script successfully +by running make -C t test-lint, which will check for things like test number +uniqueness, executable bit, and so on.

+
+
+
+

Running Locally

+
+

Let’s try and run locally:

+
+
+
+
$ make
+$ cd t/ && prove t9999-psuh-tutorial.sh
+
+
+
+

You can run the full test suite and ensure git-psuh didn’t break anything:

+
+
+
+
$ cd t/
+$ prove -j$(nproc) --shuffle t[0-9]*.sh
+
+
+
+ + + + + +
+
Note
+
+You can also do this with make test or use any testing harness which can +speak TAP. prove can run concurrently. shuffle randomizes the order the +tests are run in, which makes them resilient against unwanted inter-test +dependencies. prove also makes the output nicer. +
+
+
+

Go ahead and commit this change, as well.

+
+
+
+
+
+

Getting Ready to Share: Anatomy of a Patch Series

+
+
+

You may have noticed already that the Git project performs its code reviews via +emailed patches, which are then applied by the maintainer when they are ready +and approved by the community. The Git project does not accept contributions from +pull requests, and the patches emailed for review need to be formatted a +specific way.

+
+
+

Before taking a look at how to convert your commits into emailed patches, +let’s analyze what the end result, a "patch series", looks like. Here is an +example of the summary view for a patch series on the web interface of +the Git mailing list archive:

+
+
+
+
2022-02-18 18:40 [PATCH 0/3] libify reflog John Cai via GitGitGadget
+2022-02-18 18:40 ` [PATCH 1/3] reflog: libify delete reflog function and helpers John Cai via GitGitGadget
+2022-02-18 19:10   ` Ævar Arnfjörð Bjarmason [this message]
+2022-02-18 19:39     ` Taylor Blau
+2022-02-18 19:48       ` Ævar Arnfjörð Bjarmason
+2022-02-18 19:35   ` Taylor Blau
+2022-02-21  1:43     ` John Cai
+2022-02-21  1:50       ` Taylor Blau
+2022-02-23 19:50         ` John Cai
+2022-02-18 20:00   ` // other replies elided
+2022-02-18 18:40 ` [PATCH 2/3] reflog: call reflog_delete from reflog.c John Cai via GitGitGadget
+2022-02-18 19:15   ` Ævar Arnfjörð Bjarmason
+2022-02-18 20:26     ` Junio C Hamano
+2022-02-18 18:40 ` [PATCH 3/3] stash: call reflog_delete from reflog.c John Cai via GitGitGadget
+2022-02-18 19:20   ` Ævar Arnfjörð Bjarmason
+2022-02-19  0:21     ` Taylor Blau
+2022-02-22  2:36     ` John Cai
+2022-02-22 10:51       ` Ævar Arnfjörð Bjarmason
+2022-02-18 19:29 ` [PATCH 0/3] libify reflog Ævar Arnfjörð Bjarmason
+2022-02-22 18:30 ` [PATCH v2 0/3] libify reflog John Cai via GitGitGadget
+2022-02-22 18:30   ` [PATCH v2 1/3] stash: add test to ensure reflog --rewrite --updatref behavior John Cai via GitGitGadget
+2022-02-23  8:54     ` Ævar Arnfjörð Bjarmason
+2022-02-23 21:27       ` Junio C Hamano
+// continued
+
+
+
+

We can note a few things:

+
+
+
    +
  • +

    Each commit is sent as a separate email, with the commit message title as +subject, prefixed with "[PATCH i/n]" for the i-th commit of an +n-commit series.

    +
  • +
  • +

    Each patch is sent as a reply to an introductory email called the cover +letter of the series, prefixed "[PATCH 0/n]".

    +
  • +
  • +

    Subsequent iterations of the patch series are labelled "PATCH v2", "PATCH +v3", etc. in place of "PATCH". For example, "[PATCH v2 1/3]" would be the first of +three patches in the second iteration. Each iteration is sent with a new cover +letter (like "[PATCH v2 0/3]" above), itself a reply to the cover letter of the +previous iteration (more on that below).

    +
  • +
+
+
+ + + + + +
+
Note
+
+A single-patch topic is sent with "[PATCH]", "[PATCH v2]", etc. without +i/n numbering (in the above thread overview, no single-patch topic appears, +though). +
+
+
+

The cover letter

+
+

In addition to an email per patch, the Git community also expects your patches +to come with a cover letter. This is an important component of change +submission as it explains to the community from a high level what you’re trying +to do, and why, in a way that’s more apparent than just looking at your +patches.

+
+
+

The title of your cover letter should be something which succinctly covers the +purpose of your entire topic branch. It’s often in the imperative mood, just +like our commit message titles. Here is how we’ll title our series:

+
+
+
+

Add the psuh command +---

+
+
+

The body of the cover letter is used to give additional context to reviewers. +Be sure to explain anything your patches don’t make clear on their own, but +remember that since the cover letter is not recorded in the commit history, +anything that might be useful to future readers of the repository’s history +should also be in your commit messages.

+
+
+

Here’s an example body for psuh:

+
+
+
+
Our internal metrics indicate widespread interest in the command
+git-psuh - that is, many users are trying to use it, but finding it is
+unavailable, using some unknown workaround instead.
+
+The following handful of patches add the psuh command and implement some
+handy features on top of it.
+
+This patchset is part of the MyFirstContribution tutorial and should not
+be merged.
+
+
+
+

At this point the tutorial diverges, in order to demonstrate two +different methods of formatting your patchset and getting it reviewed.

+
+
+

The first method to be covered is GitGitGadget, which is useful for those +already familiar with GitHub’s common pull request workflow. This method +requires a GitHub account.

+
+
+

The second method to be covered is git send-email, which can give slightly +more fine-grained control over the emails to be sent. This method requires some +setup which can change depending on your system and will not be covered in this +tutorial.

+
+
+

Regardless of which method you choose, your engagement with reviewers will be +the same; the review process will be covered after the sections on GitGitGadget +and git send-email.

+
+
+
+
+
+

Sending Patches via GitGitGadget

+
+
+

One option for sending patches is to follow a typical pull request workflow and +send your patches out via GitGitGadget. GitGitGadget is a tool created by +Johannes Schindelin to make life as a Git contributor easier for those used to +the GitHub PR workflow. It allows contributors to open pull requests against its +mirror of the Git project, and does some magic to turn the PR into a set of +emails and send them out for you. It also runs the Git continuous integration +suite for you. It’s documented at https://gitgitgadget.github.io/.

+
+
+

Forking git/git on GitHub

+
+

Before you can send your patch off to be reviewed using GitGitGadget, you will +need to fork the Git project and upload your changes. First thing - make sure +you have a GitHub account.

+
+
+

Head to the GitHub mirror and look for the Fork +button. Place your fork wherever you deem appropriate and create it.

+
+
+
+

Uploading to Your Own Fork

+
+

To upload your branch to your own fork, you’ll need to add the new fork as a +remote. You can use git remote -v to show the remotes you have added already. +From your new fork’s page on GitHub, you can press "Clone or download" to get +the URL; then you need to run the following to add, replacing your own URL and +remote name for the examples provided:

+
+
+
+
$ git remote add remotename git@github.com:remotename/git.git
+
+
+
+

or to use the HTTPS URL:

+
+
+
+
$ git remote add remotename https://github.com/remotename/git/.git
+
+
+
+

Run git remote -v again and you should see the new remote showing up. +git fetch remotename (with the real name of your remote replaced) in order to +get ready to push.

+
+
+

Next, double-check that you’ve been doing all your development in a new branch +by running git branch. If you didn’t, now is a good time to move your new +commits to their own branch.

+
+
+

As mentioned briefly at the beginning of this document, we are basing our work +on master, so go ahead and update as shown below, or using your preferred +workflow.

+
+
+
+
$ git checkout master
+$ git pull -r
+$ git rebase master psuh
+
+
+
+

Finally, you’re ready to push your new topic branch! (Due to our branch and +command name choices, be careful when you type the command below.)

+
+
+
+
$ git push remotename psuh
+
+
+
+

Now you should be able to go and check out your newly created branch on GitHub.

+
+
+
+

Sending a PR to GitGitGadget

+
+

In order to have your code tested and formatted for review, you need to start by +opening a Pull Request against either gitgitgadget/git or git/git. Head to +https://github.com/gitgitgadget/git or https://github.com/git/git and open a PR +either with the "New pull request" button or the convenient "Compare & pull +request" button that may appear with the name of your newly pushed branch.

+
+
+

The differences between using gitgitgadget/git and git/git as your base can +be found [here](https://gitgitgadget.github.io/#should-i-use-gitgitgadget-on-gitgitgadgets-git-fork-or-on-gits-github-mirror)

+
+
+

Review the PR’s title and description, as they’re used by GitGitGadget +respectively as the subject and body of the cover letter for your change. Refer +to "The cover letter" above for advice on how to title your +submission and what content to include in the description.

+
+
+ + + + + +
+
Note
+
+For single-patch contributions, your commit message should already be +meaningful and explain at a high level the purpose (what is happening and why) +of your patch, so you usually do not need any additional context. In that case, +remove the PR description that GitHub automatically generates from your commit +message (your PR description should be empty). If you do need to supply even +more context, you can do so in that space and it will be appended to the email +that GitGitGadget will send, between the three-dash line and the diffstat +(see Bonus Chapter: One-Patch Changes for how this looks once +submitted). +
+
+
+

When you’re happy, submit your pull request.

+
+
+
+

Running CI and Getting Ready to Send

+
+

If it’s your first time using GitGitGadget (which is likely, as you’re using +this tutorial) then someone will need to give you permission to use the tool. +As mentioned in the GitGitGadget documentation, you just need someone who +already uses it to comment on your PR with /allow <username>. GitGitGadget +will automatically run your PRs through the CI even without the permission given +but you will not be able to /submit your changes until someone allows you to +use the tool.

+
+
+ + + + + +
+
Note
+
+You can typically find someone who can /allow you on GitGitGadget by +either examining recent pull requests where someone has been granted /allow +(Search: +is:pr is:open "/allow"), in which case both the author and the person who +granted the /allow can now /allow you, or by inquiring on the +#git-devel IRC channel on Libera Chat +linking your pull request and asking for someone to /allow you. +
+
+
+

If the CI fails, you can update your changes with git rebase -i and push your +branch again:

+
+
+
+
$ git push -f remotename psuh
+
+
+
+

In fact, you should continue to make changes this way up until the point when +your patch is accepted into next.

+
+
+
+

Sending Your Patches

+
+

Now that your CI is passing and someone has granted you permission to use +GitGitGadget with the /allow command, sending out for review is as simple as +commenting on your PR with /submit.

+
+
+
+

Updating With Comments

+
+

Skip ahead to Responding to Reviews for information on how to +reply to review comments you will receive on the mailing list.

+
+
+

Once you have your branch again in the shape you want following all review +comments, you can submit again:

+
+
+
+
$ git push -f remotename psuh
+
+
+
+

Next, go look at your pull request against GitGitGadget; you should see the CI +has been kicked off again. Now while the CI is running is a good time for you +to modify your description at the top of the pull request thread; it will be +used again as the cover letter. You should use this space to describe what +has changed since your previous version, so that your reviewers have some idea +of what they’re looking at. When the CI is done running, you can comment once +more with /submit - GitGitGadget will automatically add a v2 mark to your +changes.

+
+
+
+
+
+

Sending Patches with git send-email

+
+
+

If you don’t want to use GitGitGadget, you can also use Git itself to mail your +patches. Some benefits of using Git this way include finer grained control of +subject line (for example, being able to use the tag [RFC PATCH] in the subject) +and being able to send a “dry run” mail to yourself to ensure it all looks +good before going out to the list.

+
+
+

Prerequisite: Setting Up git send-email

+
+

Configuration for send-email can vary based on your operating system and email +provider, and so will not be covered in this tutorial, beyond stating that in +many distributions of Linux, git-send-email is not packaged alongside the +typical git install. You may need to install this additional package; there +are a number of resources online to help you do so. You will also need to +determine the right way to configure it to use your SMTP server; again, as this +configuration can change significantly based on your system and email setup, it +is out of scope for the context of this tutorial.

+
+
+
+

Preparing Initial Patchset

+
+

Sending emails with Git is a two-part process; before you can prepare the emails +themselves, you’ll need to prepare the patches. Luckily, this is pretty simple:

+
+
+
+
$ git format-patch --cover-letter -o psuh/ --base=auto psuh@{u}..psuh
+
+
+
+
    +
  1. +

    The --cover-letter option tells format-patch to create a +cover letter template for you. You will need to fill in the +template before you’re ready to send - but for now, the template +will be next to your other patches.

    +
  2. +
  3. +

    The -o psuh/ option tells format-patch to place the patch +files into a directory. This is useful because git send-email +can take a directory and send out all the patches from there.

    +
  4. +
  5. +

    The --base=auto option tells the command to record the "base +commit", on which the recipient is expected to apply the patch +series. The auto value will cause format-patch to compute +the base commit automatically, which is the merge base of tip +commit of the remote-tracking branch and the specified revision +range.

    +
  6. +
  7. +

    The psuh@{u}..psuh option tells format-patch to generate +patches for the commits you created on the psuh branch since it +forked from its upstream (which is origin/master if you +followed the example in the "Set up your workspace" section). If +you are already on the psuh branch, you can just say @{u}, +which means "commits on the current branch since it forked from +its upstream", which is the same thing.

    +
  8. +
+
+
+

The command will make one patch file per commit. After you +run, you can go have a look at each of the patches with your favorite text +editor and make sure everything looks alright; however, it’s not recommended to +make code fixups via the patch file. It’s a better idea to make the change the +normal way using git rebase -i or by adding a new commit than by modifying a +patch.

+
+
+ + + + + +
+
Note
+
+Optionally, you can also use the --rfc flag to prefix your patch subject +with “[RFC PATCH]” instead of “[PATCH]”. RFC stands for “request for +comments” and indicates that while your code isn’t quite ready for submission, +you’d like to begin the code review process. This can also be used when your +patch is a proposal, but you aren’t sure whether the community wants to solve +the problem with that approach or not - to conduct a sort of design review. You +may also see on the list patches marked “WIP” - this means they are incomplete +but want reviewers to look at what they have so far. You can add this flag with +--subject-prefix=WIP. +
+
+
+

Check and make sure that your patches and cover letter template exist in the +directory you specified - you’re nearly ready to send out your review!

+
+
+
+

Preparing Email

+
+

Since you invoked format-patch with --cover-letter, you’ve already got a +cover letter template ready. Open it up in your favorite editor.

+
+
+

You should see a number of headers present already. Check that your From: +header is correct. Then modify your Subject: (see above for +how to choose good title for your patch series):

+
+
+
+
Subject: [PATCH 0/7] Add the 'psuh' command
+
+
+
+

Make sure you retain the “[PATCH 0/X]” part; that’s what indicates to the Git +community that this email is the beginning of a patch series, and many +reviewers filter their email for this type of flag.

+
+
+

You’ll need to add some extra parameters when you invoke git send-email to add +the cover letter.

+
+
+

Next you’ll have to fill out the body of your cover letter. Again, see +above for what content to include.

+
+
+

The template created by git format-patch --cover-letter includes a diffstat. +This gives reviewers a summary of what they’re in for when reviewing your topic. +The one generated for psuh from the sample implementation looks like this:

+
+
+
+
 Documentation/git-psuh.adoc | 40 +++++++++++++++++++++
+ Makefile                    |  1 +
+ builtin.h                   |  1 +
+ builtin/psuh.c              | 73 ++++++++++++++++++++++++++++++++++++++
+ git.c                       |  1 +
+ t/t9999-psuh-tutorial.sh    | 12 +++++++
+ 6 files changed, 128 insertions(+)
+ create mode 100644 Documentation/git-psuh.adoc
+ create mode 100644 builtin/psuh.c
+ create mode 100755 t/t9999-psuh-tutorial.sh
+
+
+
+

Finally, the letter will include the version of Git used to generate the +patches. You can leave that string alone.

+
+
+
+

Sending Email

+
+

At this point you should have a directory psuh/ which is filled with your +patches and a cover letter. Time to mail it out! You can send it like this:

+
+
+
+
$ git send-email --to=target@example.com psuh/*.patch
+
+
+
+ + + + + +
+
Note
+
+Check git help send-email for some other options which you may find +valuable, such as changing the Reply-to address or adding more CC and BCC lines. +
+
+
+ + + + + +
+
Note
+
+If you’re not sure whom to CC, running contrib/contacts/git-contacts can +list potential reviewers. In addition, you can do git send-email +--cc-cmd='perl contrib/contacts/git-contacts' feature/*.patch[1] to +automatically pass this list of emails to send-email. +
+
+
+ + + + + +
+
Note
+
+When you are sending a real patch, it will go to git@vger.kernel.org - but +please don’t send your patchset from the tutorial to the real mailing list! For +now, you can send it to yourself, to make sure you understand how it will look. +
+
+
+ + + + + +
+
Note
+
+After sending your patches, you can confirm that they reached the mailing +list by visiting https://lore.kernel.org/git/. Use the search bar to find your +name or the subject of your patch. If it appears, your email was successfully +delivered. +
+
+
+

After you run the command above, you will be presented with an interactive +prompt for each patch that’s about to go out. This gives you one last chance to +edit or quit sending something (but again, don’t edit code this way). Once you +press y or a at these prompts your emails will be sent! Congratulations!

+
+
+

Awesome, now the community will drop everything and review your changes. (Just +kidding - be patient!)

+
+
+
+

Sending v2

+
+

This section will focus on how to send a v2 of your patchset. To learn what +should go into v2, skip ahead to Responding to Reviews for +information on how to handle comments from reviewers.

+
+
+

We’ll reuse our psuh topic branch for v2. Before we make any changes, we’ll +mark the tip of our v1 branch for easy reference:

+
+
+
+
$ git checkout psuh
+$ git branch psuh-v1
+
+
+
+

Refine your patch series by using git rebase -i to adjust commits based upon +reviewer comments. Once the patch series is ready for submission, generate your +patches again, but with some new flags:

+
+
+
+
$ git format-patch -v2 --cover-letter -o psuh/ --range-diff master..psuh-v1 master..
+
+
+
+

The --range-diff master..psuh-v1 parameter tells format-patch to include a +range-diff between psuh-v1 and psuh in the cover letter (see +git-range-diff(1)). This helps tell reviewers about the differences +between your v1 and v2 patches.

+
+
+

The -v2 parameter tells format-patch to output your patches +as version "2". For instance, you may notice that your v2 patches are +all named like v2-000n-my-commit-subject.patch. -v2 will also format +your patches by prefixing them with "[PATCH v2]" instead of "[PATCH]", +and your range-diff will be prefaced with "Range-diff against v1".

+
+
+

After you run this command, format-patch will output the patches to the psuh/ +directory, alongside the v1 patches. Using a single directory makes it easy to +refer to the old v1 patches while proofreading the v2 patches, but you will need +to be careful to send out only the v2 patches. We will use a pattern like +psuh/v2-*.patch (not psuh/*.patch, which would match v1 and v2 patches).

+
+
+

Edit your cover letter again. Now is a good time to mention what’s different +between your last version and now, if it’s something significant. You do not +need the exact same body in your second cover letter; focus on explaining to +reviewers the changes you’ve made that may not be as visible.

+
+
+

You will also need to go and find the Message-ID of your previous cover letter. +You can either note it when you send the first series, from the output of git +send-email, or you can look it up on the +mailing list. Find your cover letter in the +archives, click on it, then click "permalink" or "raw" to reveal the Message-ID +header. It should match:

+
+
+
+
Message-ID: <foo.12345.author@example.com>
+
+
+
+

Your Message-ID is <foo.12345.author@example.com>. This example will be used +below as well; make sure to replace it with the correct Message-ID for your +previous cover letter - that is, if you’re sending v2, use the Message-ID +from v1; if you’re sending v3, use the Message-ID from v2.

+
+
+

While you’re looking at the email, you should also note who is CC’d, as it’s +common practice in the mailing list to keep all CCs on a thread. You can add +these CC lines directly to your cover letter with a line like so in the header +(before the Subject line):

+
+
+
+
CC: author@example.com, Othe R <other@example.com>
+
+
+
+

Now send the emails again, paying close attention to which messages you pass in +to the command:

+
+
+
+
$ git send-email --to=target@example.com
+                 --in-reply-to="<foo.12345.author@example.com>"
+                 psuh/v2-*.patch
+
+
+
+
+

Bonus Chapter: One-Patch Changes

+
+

In some cases, your very small change may consist of only one patch. When that +happens, you only need to send one email. Your commit message should already be +meaningful and explain at a high level the purpose (what is happening and why) +of your patch, but if you need to supply even more context, you can do so below +the --- in your patch. Take the example below, which was generated with git +format-patch on a single commit, and then edited to add the content between +the --- and the diffstat.

+
+
+
+
From 1345bbb3f7ac74abde040c12e737204689a72723 Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Thu, 18 Apr 2019 15:11:02 -0700
+Subject: [PATCH] README: change the grammar
+
+I think it looks better this way. This part of the commit message will
+end up in the commit-log.
+
+Signed-off-by: A U Thor <author@example.com>
+---
+Let's have a wild discussion about grammar on the mailing list. This
+part of my email will never end up in the commit log. Here is where I
+can add additional context to the mailing list about my intent, outside
+of the context of the commit log. This section was added after `git
+format-patch` was run, by editing the patch file in a text editor.
+
+ README.md | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/README.md b/README.md
+index 88f126184c..38da593a60 100644
+--- a/README.md
++++ b/README.md
+@@ -3,7 +3,7 @@
+ Git - fast, scalable, distributed revision control system
+ =========================================================
+
+-Git is a fast, scalable, distributed revision control system with an
++Git is a fast, scalable, and distributed revision control system with an
+ unusually rich command set that provides both high-level operations
+ and full access to internals.
+
+--
+2.21.0.392.gf8f6787159e-goog
+
+
+
+
+
+
+

My Patch Got Emailed - Now What?

+
+
+

Please give reviewers enough time to process your initial patch before +sending an updated version. That is, resist the temptation to send a new +version immediately, because others may have already started reviewing +your initial version.

+
+
+

While waiting for review comments, you may find mistakes in your initial +patch, or perhaps realize a different and better way to achieve the goal +of the patch. In this case you may communicate your findings to other +reviewers as follows:

+
+
+
    +
  • +

    If the mistakes you found are minor, send a reply to your patch as if +you were a reviewer and mention that you will fix them in an +updated version.

    +
  • +
  • +

    On the other hand, if you think you want to change the course so +drastically that reviews on the initial patch would be a waste of +time (for everyone involved), retract the patch immediately with +a reply like "I am working on a much better approach, so please +ignore this patch and wait for the updated version."

    +
  • +
+
+
+

Now, the above is a good practice if you sent your initial patch +prematurely without polish. But a better approach of course is to avoid +sending your patch prematurely in the first place.

+
+
+

Please be considerate of the time needed by reviewers to examine each +new version of your patch. Rather than seeing the initial version right +now (followed by several "oops, I like this version better than the +previous one" patches over 2 days), reviewers would strongly prefer if a +single polished version came 2 days later instead, and that version with +fewer mistakes were the only one they would need to review.

+
+
+

Responding to Reviews

+
+

After a few days, you will hopefully receive a reply to your patchset with some +comments. Woohoo! Now you can get back to work.

+
+
+

It’s good manners to reply to each comment, notifying the reviewer that you have +made the change suggested, feel the original is better, or that the comment +inspired you to do something a new way which is superior to both the original +and the suggested change. This way reviewers don’t need to inspect your v2 to +figure out whether you implemented their comment or not.

+
+
+

Reviewers may ask you about what you wrote in the patchset, either in +the proposed commit log message or in the changes themselves. You +should answer these questions in your response messages, but often the +reason why reviewers asked these questions to understand what you meant +to write is because your patchset needed clarification to be understood.

+
+
+

Do not be satisfied by just answering their questions in your response +and hear them say that they now understand what you wanted to say. +Update your patches to clarify the points reviewers had trouble with, +and prepare your v2; the words you used to explain your v1 to answer +reviewers' questions may be useful thing to use. Your goal is to make +your v2 clear enough so that it becomes unnecessary for you to give the +same explanation to the next person who reads it.

+
+
+

If you are going to push back on a comment, be polite and explain why you feel +your original is better; be prepared that the reviewer may still disagree with +you, and the rest of the community may weigh in on one side or the other. As +with all code reviews, it’s important to keep an open mind to doing something a +different way than you originally planned; other reviewers have a different +perspective on the project than you do, and may be thinking of a valid side +effect which had not occurred to you. It is always okay to ask for clarification +if you aren’t sure why a change was suggested, or what the reviewer is asking +you to do.

+
+
+

Make sure your email client has a plaintext email mode and it is turned on; the +Git list rejects HTML email. Please also follow the mailing list etiquette +outlined in the +Maintainer’s +Note, which are similar to etiquette rules in most open source communities +surrounding bottom-posting and inline replies.

+
+
+

When you’re making changes to your code, it is cleanest - that is, the resulting +commits are easiest to look at - if you use git rebase -i (interactive +rebase). Take a look at this +overview +from O’Reilly. The general idea is to modify each commit which requires changes; +this way, instead of having a patch A with a mistake, a patch B which was fine +and required no upstream reviews in v1, and a patch C which fixes patch A for +v2, you can just ship a v2 with a correct patch A and correct patch B. This is +changing history, but since it’s local history which you haven’t shared with +anyone, that is okay for now! (Later, it may not make sense to do this; take a +look at the section below this one for some context.)

+
+
+
+

After Review Approval

+
+

The Git project has four integration branches: seen, next, master, and +maint. Your change will be placed into seen fairly early on by the maintainer +while it is still in the review process; from there, when it is ready for wider +testing, it will be merged into next. Plenty of early testers use next and +may report issues. Eventually, changes in next will make it to master, +which is typically considered stable. Finally, when a new release is cut, +maint is used to base bugfixes onto. As mentioned at the beginning of this +document, you can read Documents/SubmittingPatches for some more info about +the use of the various integration branches.

+
+
+

Back to now: your code has been lauded by the upstream reviewers. It is perfect. +It is ready to be accepted. You don’t need to do anything else; the maintainer +will merge your topic branch to next and life is good.

+
+
+

However, if you discover it isn’t so perfect after this point, you may need to +take some special steps depending on where you are in the process.

+
+
+

If the maintainer has announced in the "What’s cooking in git.git" email that +your topic is marked for next - that is, that they plan to merge it to next +but have not yet done so - you should send an email asking the maintainer to +wait a little longer: "I’ve sent v4 of my series and you marked it for next, +but I need to change this and that - please wait for v5 before you merge it."

+
+
+

If the topic has already been merged to next, rather than modifying your +patches with git rebase -i, you should make further changes incrementally - +that is, with another commit, based on top of the maintainer’s topic branch as +detailed in https://github.com/gitster/git. Your work is still in the same topic +but is now incremental, rather than a wholesale rewrite of the topic branch.

+
+
+

The topic branches in the maintainer’s GitHub are mirrored in GitGitGadget, so +if you’re sending your reviews out that way, you should be sure to open your PR +against the appropriate GitGitGadget/Git branch.

+
+
+

If you’re using git send-email, you can use it the same way as before, but you +should generate your diffs from <topic>..<mybranch> and base your work on +<topic> instead of master.

+
+
+
+
+
+
+
+
+1. Scripts under `contrib/` are not part of the core `git` binary and must be called directly. Clone the Git codebase and run `perl contrib/contacts/git-contacts`. +
+
+ + + \ No newline at end of file diff --git a/MyFirstObjectWalk.adoc b/MyFirstObjectWalk.adoc new file mode 100644 index 000000000..413a9fdb0 --- /dev/null +++ b/MyFirstObjectWalk.adoc @@ -0,0 +1,913 @@ += My First Object Walk + +== What's an Object Walk? + +The object walk is a key concept in Git - this is the process that underpins +operations like object transfer and fsck. Beginning from a given commit, the +list of objects is found by walking parent relationships between commits (commit +X based on commit W) and containment relationships between objects (tree Y is +contained within commit X, and blob Z is located within tree Y, giving our +working tree for commit X something like `y/z.txt`). + +A related concept is the revision walk, which is focused on commit objects and +their parent relationships and does not delve into other object types. The +revision walk is used for operations like `git log`. + +=== Related Reading + +- `Documentation/user-manual.adoc` under "Hacking Git" contains some coverage of + the revision walker in its various incarnations. +- `revision.h` +- https://eagain.net/articles/git-for-computer-scientists/[Git for Computer Scientists] + gives a good overview of the types of objects in Git and what your object + walk is really describing. + +== Setting Up + +Create a new branch from `master`. + +---- +git checkout -b revwalk origin/master +---- + +We'll put our fiddling into a new command. For fun, let's name it `git walken`. +Open up a new file `builtin/walken.c` and set up the command handler: + +---- +/* + * "git walken" + * + * Part of the "My First Object Walk" tutorial. + */ + +#include "builtin.h" +#include "trace.h" + +int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo) +{ + trace_printf(_("cmd_walken incoming...\n")); + return 0; +} +---- + +NOTE: `trace_printf()`, defined in `trace.h`, differs from `printf()` in +that it can be turned on or off at runtime. For the purposes of this +tutorial, we will write `walken` as though it is intended for use as +a "plumbing" command: that is, a command which is used primarily in +scripts, rather than interactively by humans (a "porcelain" command). +So we will send our debug output to `trace_printf()` instead. +When running, enable trace output by setting the environment variable `GIT_TRACE`. + +Add usage text and `-h` handling, like all subcommands should consistently do +(our test suite will notice and complain if you fail to do so). +We'll need to include the `parse-options.h` header. + +---- +#include "parse-options.h" + +... + +int cmd_walken(int argc, const char **argv, const char *prefix) +{ + const char * const walken_usage[] = { + N_("git walken"), + NULL, + }; + struct option options[] = { + OPT_END() + }; + + argc = parse_options(argc, argv, prefix, options, walken_usage, 0); + + ... +} +---- + +Also add the relevant line in `builtin.h` near `cmd_version()`: + +---- +int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo); +---- + +Include the command in `git.c` in `commands[]` near the entry for `version`, +maintaining alphabetical ordering: + +---- +{ "walken", cmd_walken, RUN_SETUP }, +---- + +Add an entry for the new command in the both the Make and Meson build system, +before the entry for `worktree`: + +- In the `Makefile`: +---- +... +BUILTIN_OBJS += builtin/walken.o +... +---- + +- In the `meson.build` file: +---- +builtin_sources = [ + ... + 'builtin/walken.c', + ... +] +---- + +Build and test out your command, without forgetting to ensure the `DEVELOPER` +flag is set, and with `GIT_TRACE` enabled so the debug output can be seen: + +---- +$ echo DEVELOPER=1 >>config.mak +$ make +$ GIT_TRACE=1 ./bin-wrappers/git walken +---- + +NOTE: For a more exhaustive overview of the new command process, take a look at +`Documentation/MyFirstContribution.adoc`. + +NOTE: A reference implementation can be found at +https://github.com/nasamuffin/git/tree/revwalk. + +=== `struct rev_cmdline_info` + +The definition of `struct rev_cmdline_info` can be found in `revision.h`. + +This struct is contained within the `rev_info` struct and is used to reflect +parameters provided by the user over the CLI. + +`nr` represents the number of `rev_cmdline_entry` present in the array. + +`alloc` is used by the `ALLOC_GROW` macro. Check `alloc.h` - this variable is +used to track the allocated size of the list. + +Per entry, we find: + +`item` is the object provided upon which to base the object walk. Items in Git +can be blobs, trees, commits, or tags. (See `Documentation/gittutorial-2.adoc`.) + +`name` is the object ID (OID) of the object - a hex string you may be familiar +with from using Git to organize your source in the past. Check the tutorial +mentioned above towards the top for a discussion of where the OID can come +from. + +`whence` indicates some information about what to do with the parents of the +specified object. We'll explore this flag more later on; take a look at +`Documentation/revisions.adoc` to get an idea of what could set the `whence` +value. + +`flags` are used to hint the beginning of the revision walk and are the first +block under the `#include`s in `revision.h`. The most likely ones to be set in +the `rev_cmdline_info` are `UNINTERESTING` and `BOTTOM`, but these same flags +can be used during the walk, as well. + +=== `struct rev_info` + +This one is quite a bit longer, and many fields are only used during the walk +by `revision.c` - not configuration options. Most of the configurable flags in +`struct rev_info` have a mirror in `Documentation/rev-list-options.adoc`. It's a +good idea to take some time and read through that document. + +== Basic Commit Walk + +First, let's see if we can replicate the output of `git log --oneline`. We'll +refer back to the implementation frequently to discover norms when performing +an object walk of our own. + +To do so, we'll first find all the commits, in order, which preceded the current +commit. We'll extract the name and subject of the commit from each. + +Ideally, we will also be able to find out which ones are currently at the tip of +various branches. + +=== Setting Up + +Preparing for your object walk has some distinct stages. + +1. Perform default setup for this mode, and others which may be invoked. +2. Check configuration files for relevant settings. +3. Set up the `rev_info` struct. +4. Tweak the initialized `rev_info` to suit the current walk. +5. Prepare the `rev_info` for the walk. +6. Iterate over the objects, processing each one. + +==== Default Setups + +Before examining configuration files which may modify command behavior, set up +default state for switches or options your command may have. If your command +utilizes other Git components, ask them to set up their default states as well. +For instance, `git log` takes advantage of `grep` and `diff` functionality, so +its `init_log_defaults()` sets its own state (`decoration_style`) and asks +`grep` and `diff` to initialize themselves by calling each of their +initialization functions. + +==== Configuring From `.gitconfig` + +Next, we should have a look at any relevant configuration settings (i.e., +settings readable and settable from `git config`). This is done by providing a +callback to `repo_config()`; within that callback, you can also invoke methods +from other components you may need that need to intercept these options. Your +callback will be invoked once per each configuration value which Git knows about +(global, local, worktree, etc.). + +Similarly to the default values, we don't have anything to do here yet +ourselves; however, we should call `git_default_config()` if we aren't calling +any other existing config callbacks. + +Add a new function to `builtin/walken.c`. +We'll also need to include the `config.h` header: + +---- +#include "config.h" + +... + +static int git_walken_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) +{ + /* + * For now, we don't have any custom configuration, so fall back to + * the default config. + */ + return git_default_config(var, value, ctx, cb); +} +---- + +Make sure to invoke `repo_config()` with it in your `cmd_walken()`: + +---- +int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo) +{ + ... + + repo_config(repo, git_walken_config, NULL); + + ... +} +---- + +==== Setting Up `rev_info` + +Now that we've gathered external configuration and options, it's time to +initialize the `rev_info` object which we will use to perform the walk. This is +typically done by calling `repo_init_revisions()` with the repository you intend +to target, as well as the `prefix` argument of `cmd_walken` and your `rev_info` +struct. + +Add the `struct rev_info` and the `repo_init_revisions()` call. +We'll also need to include the `revision.h` header: + +---- +#include "revision.h" + +... + +int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo) +{ + /* This can go wherever you like in your declarations.*/ + struct rev_info rev; + ... + + /* This should go after the repo_config() call. */ + repo_init_revisions(repo, &rev, prefix); + + ... +} +---- + +==== Tweaking `rev_info` For the Walk + +We're getting close, but we're still not quite ready to go. Now that `rev` is +initialized, we can modify it to fit our needs. This is usually done within a +helper for clarity, so let's add one: + +---- +static void final_rev_info_setup(struct rev_info *rev) +{ + /* + * We want to mimic the appearance of `git log --oneline`, so let's + * force oneline format. + */ + get_commit_format("oneline", rev); + + /* Start our object walk at HEAD. */ + add_head_to_pending(rev); +} +---- + +[NOTE] +==== +Instead of using the shorthand `add_head_to_pending()`, you could do +something like this: + +---- + struct setup_revision_opt opt; + + memset(&opt, 0, sizeof(opt)); + opt.def = "HEAD"; + opt.revarg_opt = REVARG_COMMITTISH; + setup_revisions(argc, argv, rev, &opt); +---- + +Using a `setup_revision_opt` gives you finer control over your walk's starting +point. +==== + +Then let's invoke `final_rev_info_setup()` after the call to +`repo_init_revisions()`: + +---- +int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo) +{ + ... + + final_rev_info_setup(&rev); + + ... +} +---- + +Later, we may wish to add more arguments to `final_rev_info_setup()`. But for +now, this is all we need. + +==== Preparing `rev_info` For the Walk + +Now that `rev` is all initialized and configured, we've got one more setup step +before we get rolling. We can do this in a helper, which will both prepare the +`rev_info` for the walk, and perform the walk itself. Let's start the helper +with the call to `prepare_revision_walk()`, which can return an error without +dying on its own: + +---- +static void walken_commit_walk(struct rev_info *rev) +{ + if (prepare_revision_walk(rev)) + die(_("revision walk setup failed")); +} +---- + +NOTE: `die()` prints to `stderr` and exits the program. Since it will print to +`stderr` it's likely to be seen by a human, so we will localize it. + +==== Performing the Walk! + +Finally! We are ready to begin the walk itself. Now we can see that `rev_info` +can also be used as an iterator; we move to the next item in the walk by using +`get_revision()` repeatedly. Add the listed variable declarations at the top and +the walk loop below the `prepare_revision_walk()` call within your +`walken_commit_walk()`: + +---- +#include "pretty.h" + +... + +static void walken_commit_walk(struct rev_info *rev) +{ + struct commit *commit; + struct strbuf prettybuf = STRBUF_INIT; + + ... + + while ((commit = get_revision(rev))) { + strbuf_reset(&prettybuf); + pp_commit_easy(CMIT_FMT_ONELINE, commit, &prettybuf); + puts(prettybuf.buf); + } + strbuf_release(&prettybuf); +} +---- + +NOTE: `puts()` prints a `char*` to `stdout`. Since this is the part of the +command we expect to be machine-parsed, we're sending it directly to stdout. + +Give it a shot. + +---- +$ make +$ ./bin-wrappers/git walken +---- + +You should see all of the subject lines of all the commits in +your tree's history, in order, ending with the initial commit, "Initial revision +of "git", the information manager from hell". Congratulations! You've written +your first revision walk. You can play with printing some additional fields +from each commit if you're curious; have a look at the functions available in +`commit.h`. + +=== Adding a Filter + +Next, let's try to filter the commits we see based on their author. This is +equivalent to running `git log --author=`. We can add a filter by +modifying `rev_info.grep_filter`, which is a `struct grep_opt`. + +First some setup. Add `grep_config()` to `git_walken_config()`: + +---- +static int git_walken_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) +{ + grep_config(var, value, ctx, cb); + return git_default_config(var, value, ctx, cb); +} +---- + +Next, we can modify the `grep_filter`. This is done with convenience functions +found in `grep.h`. For fun, we're filtering to only commits from folks using a +`gmail.com` email address - a not-very-precise guess at who may be working on +Git as a hobby. Since we're checking the author, which is a specific line in the +header, we'll use the `append_header_grep_pattern()` helper. We can use +the `enum grep_header_field` to indicate which part of the commit header we want +to search. + +In `final_rev_info_setup()`, add your filter line: + +---- +static void final_rev_info_setup(int argc, const char **argv, + const char *prefix, struct rev_info *rev) +{ + ... + + append_header_grep_pattern(&rev->grep_filter, GREP_HEADER_AUTHOR, + "gmail"); + compile_grep_patterns(&rev->grep_filter); + + ... +} +---- + +`append_header_grep_pattern()` adds your new "gmail" pattern to `rev_info`, but +it won't work unless we compile it with `compile_grep_patterns()`. + +NOTE: If you are using `setup_revisions()` (for example, if you are passing a +`setup_revision_opt` instead of using `add_head_to_pending()`), you don't need +to call `compile_grep_patterns()` because `setup_revisions()` calls it for you. + +NOTE: We could add the same filter via the `append_grep_pattern()` helper if we +wanted to, but `append_header_grep_pattern()` adds the `enum grep_context` and +`enum grep_pat_token` for us. + +=== Changing the Order + +There are a few ways that we can change the order of the commits during a +revision walk. Firstly, we can use the `enum rev_sort_order` to choose from some +typical orderings. + +`topo_order` is the same as `git log --topo-order`: we avoid showing a parent +before all of its children have been shown, and we avoid mixing commits which +are in different lines of history. (`git help log`'s section on `--topo-order` +has a very nice diagram to illustrate this.) + +Let's see what happens when we run with `REV_SORT_BY_COMMIT_DATE` as opposed to +`REV_SORT_BY_AUTHOR_DATE`. Add the following: + +---- +static void final_rev_info_setup(int argc, const char **argv, + const char *prefix, struct rev_info *rev) +{ + ... + + rev->topo_order = 1; + rev->sort_order = REV_SORT_BY_COMMIT_DATE; + + ... +} +---- + +Let's output this into a file so we can easily diff it with the walk sorted by +author date. + +---- +$ make +$ ./bin-wrappers/git walken > commit-date.txt +---- + +Then, let's sort by author date and run it again. + +---- +static void final_rev_info_setup(int argc, const char **argv, + const char *prefix, struct rev_info *rev) +{ + ... + + rev->topo_order = 1; + rev->sort_order = REV_SORT_BY_AUTHOR_DATE; + + ... +} +---- + +---- +$ make +$ ./bin-wrappers/git walken > author-date.txt +---- + +Finally, compare the two. This is a little less helpful without object names or +dates, but hopefully we get the idea. + +---- +$ diff -u commit-date.txt author-date.txt +---- + +This display indicates that commits can be reordered after they're written, for +example with `git rebase`. + +Let's try one more reordering of commits. `rev_info` exposes a `reverse` flag. +Set that flag somewhere inside of `final_rev_info_setup()`: + +---- +static void final_rev_info_setup(int argc, const char **argv, const char *prefix, + struct rev_info *rev) +{ + ... + + rev->reverse = 1; + + ... +} +---- + +Run your walk again and note the difference in order. (If you remove the grep +pattern, you should see the last commit this call gives you as your current +HEAD.) + +== Basic Object Walk + +So far we've been walking only commits. But Git has more types of objects than +that! Let's see if we can walk _all_ objects, and find out some information +about each one. + +We can base our work on an example. `git pack-objects` prepares all kinds of +objects for packing into a bitmap or packfile. The work we are interested in +resides in `builtin/pack-objects.c:get_object_list()`; examination of that +function shows that the all-object walk is being performed by +`traverse_commit_list()` or `traverse_commit_list_filtered()`. Those two +functions reside in `list-objects.c`; examining the source shows that, despite +the name, these functions traverse all kinds of objects. Let's have a look at +the arguments to `traverse_commit_list()`. + +- `struct rev_info *revs`: This is the `rev_info` used for the walk. If + its `filter` member is not `NULL`, then `filter` contains information for + how to filter the object list. +- `show_commit_fn show_commit`: A callback which will be used to handle each + individual commit object. +- `show_object_fn show_object`: A callback which will be used to handle each + non-commit object (so each blob, tree, or tag). +- `void *show_data`: A context buffer which is passed in turn to `show_commit` + and `show_object`. + +In addition, `traverse_commit_list_filtered()` has an additional parameter: + +- `struct oidset *omitted`: A linked-list of object IDs which the provided + filter caused to be omitted. + +It looks like these methods use callbacks we provide instead of needing us +to call it repeatedly ourselves. Cool! Let's add the callbacks first. + +For the sake of this tutorial, we'll simply keep track of how many of each kind +of object we find. At file scope in `builtin/walken.c` add the following +tracking variables: + +---- +static int commit_count; +static int tag_count; +static int blob_count; +static int tree_count; +---- + +Commits are handled by a different callback than other objects; let's do that +one first: + +---- +static void walken_show_commit(struct commit *cmt, void *buf) +{ + commit_count++; +} +---- + +The `cmt` argument is fairly self-explanatory. But it's worth mentioning that +the `buf` argument is actually the context buffer that we can provide to the +traversal calls - `show_data`, which we mentioned a moment ago. + +Since we have the `struct commit` object, we can look at all the same parts that +we looked at in our earlier commit-only walk. For the sake of this tutorial, +though, we'll just increment the commit counter and move on. + +The callback for non-commits is a little different, as we'll need to check +which kind of object we're dealing with: + +---- +static void walken_show_object(struct object *obj, const char *str, void *buf) +{ + switch (obj->type) { + case OBJ_TREE: + tree_count++; + break; + case OBJ_BLOB: + blob_count++; + break; + case OBJ_TAG: + tag_count++; + break; + case OBJ_COMMIT: + BUG("unexpected commit object in walken_show_object\n"); + default: + BUG("unexpected object type %s in walken_show_object\n", + type_name(obj->type)); + } +} +---- + +Again, `obj` is fairly self-explanatory, and we can guess that `buf` is the same +context pointer that `walken_show_commit()` receives: the `show_data` argument +to `traverse_commit_list()` and `traverse_commit_list_filtered()`. Finally, +`str` contains the name of the object, which ends up being something like +`foo.txt` (blob), `bar/baz` (tree), or `v1.2.3` (tag). + +To help assure us that we aren't double-counting commits, we'll include some +complaining if a commit object is routed through our non-commit callback; we'll +also complain if we see an invalid object type. Since those two cases should be +unreachable, and would only change in the event of a semantic change to the Git +codebase, we complain by using `BUG()` - which is a signal to a developer that +the change they made caused unintended consequences, and the rest of the +codebase needs to be updated to understand that change. `BUG()` is not intended +to be seen by the public, so it is not localized. + +Our main object walk implementation is substantially different from our commit +walk implementation, so let's make a new function to perform the object walk. We +can perform setup which is applicable to all objects here, too, to keep separate +from setup which is applicable to commit-only walks. + +We'll start by enabling all types of objects in the `struct rev_info`. We'll +also turn on `tree_blobs_in_commit_order`, which means that we will walk a +commit's tree and everything it points to immediately after we find each commit, +as opposed to waiting for the end and walking through all trees after the commit +history has been discovered. With the appropriate settings configured, we are +ready to call `prepare_revision_walk()`. + +---- +static void walken_object_walk(struct rev_info *rev) +{ + rev->tree_objects = 1; + rev->blob_objects = 1; + rev->tag_objects = 1; + rev->tree_blobs_in_commit_order = 1; + + if (prepare_revision_walk(rev)) + die(_("revision walk setup failed")); + + commit_count = 0; + tag_count = 0; + blob_count = 0; + tree_count = 0; +---- + +Let's start by calling just the unfiltered walk and reporting our counts. +Complete your implementation of `walken_object_walk()`. +We'll also need to include the `list-objects.h` header. + +---- +#include "list-objects.h" + +... + + traverse_commit_list(rev, walken_show_commit, walken_show_object, NULL); + + printf("commits %d\nblobs %d\ntags %d\ntrees %d\n", commit_count, + blob_count, tag_count, tree_count); +} +---- + +NOTE: This output is intended to be machine-parsed. Therefore, we are not +sending it to `trace_printf()`, and we are not localizing it - we need scripts +to be able to count on the formatting to be exactly the way it is shown here. +If we were intending this output to be read by humans, we would need to localize +it with `_()`. + +Finally, we'll ask `cmd_walken()` to use the object walk instead. Discussing +command line options is out of scope for this tutorial, so we'll just hardcode +a branch we can change at compile time. Where you call `final_rev_info_setup()` +and `walken_commit_walk()`, instead branch like so: + +---- + if (1) { + add_head_to_pending(&rev); + walken_object_walk(&rev); + } else { + final_rev_info_setup(argc, argv, prefix, &rev); + walken_commit_walk(&rev); + } +---- + +NOTE: For simplicity, we've avoided all the filters and sorts we applied in +`final_rev_info_setup()` and simply added `HEAD` to our pending queue. If you +want, you can certainly use the filters we added before by moving +`final_rev_info_setup()` out of the conditional and removing the call to +`add_head_to_pending()`. + +Now we can try to run our command! It should take noticeably longer than the +commit walk, but an examination of the output will give you an idea why. Your +output should look similar to this example, but with different counts: + +---- +Object walk completed. Found 55733 commits, 100274 blobs, 0 tags, and 104210 trees. +---- + +This makes sense. We have more trees than commits because the Git project has +lots of subdirectories which can change, plus at least one tree per commit. We +have no tags because we started on a commit (`HEAD`) and while tags can point to +commits, commits can't point to tags. + +NOTE: You will have different counts when you run this yourself! The number of +objects grows along with the Git project. + +=== Adding a Filter + +There are a handful of filters that we can apply to the object walk laid out in +`Documentation/rev-list-options.adoc`. These filters are typically useful for +operations such as creating packfiles or performing a partial clone. They are +defined in `list-objects-filter-options.h`. For the purposes of this tutorial we +will use the "tree:1" filter, which causes the walk to omit all trees and blobs +which are not directly referenced by commits reachable from the commit in +`pending` when the walk begins. (`pending` is the list of objects which need to +be traversed during a walk; you can imagine a breadth-first tree traversal to +help understand. In our case, that means we omit trees and blobs not directly +referenced by `HEAD` or `HEAD`'s history, because we begin the walk with only +`HEAD` in the `pending` list.) + +For now, we are not going to track the omitted objects, so we'll replace those +parameters with `NULL`. For the sake of simplicity, we'll add a simple +build-time branch to use our filter or not. Preface the line calling +`traverse_commit_list()` with the following, which will remind us which kind of +walk we've just performed: + +---- + if (0) { + /* Unfiltered: */ + trace_printf(_("Unfiltered object walk.\n")); + } else { + trace_printf( + _("Filtered object walk with filterspec 'tree:1'.\n")); + + parse_list_objects_filter(&rev->filter, "tree:1"); + } + traverse_commit_list(rev, walken_show_commit, + walken_show_object, NULL); +---- + +The `rev->filter` member is usually built directly from a command +line argument, so the module provides an easy way to build one from a string. +Even though we aren't taking user input right now, we can still build one with +a hardcoded string using `parse_list_objects_filter()`. + +With the filter spec "tree:1", we are expecting to see _only_ the root tree for +each commit; therefore, the tree object count should be less than or equal to +the number of commits. (For an example of why that's true: `git commit --revert` +points to the same tree object as its grandparent.) + +=== Counting Omitted Objects + +We also have the capability to enumerate all objects which were omitted by a +filter, like with `git log --filter= --filter-print-omitted`. To do this, +change `traverse_commit_list()` to `traverse_commit_list_filtered()`, which is +able to populate an `omitted` list. Asking for this list of filtered objects +may cause performance degradations, however, because in this case, despite +filtering objects, the possibly much larger set of all reachable objects must +be processed in order to populate that list. + +First, add the `struct oidset` and related items we will use to iterate it: + +---- +#include "oidset.h" + +... + +static void walken_object_walk( + ... + + struct oidset omitted; + struct oidset_iter oit; + struct object_id *oid = NULL; + int omitted_count = 0; + oidset_init(&omitted, 0); + + ... +---- + +Replace the call to `traverse_commit_list()` with +`traverse_commit_list_filtered()` and pass a pointer to the `omitted` oidset +defined and initialized above: + +---- + ... + + traverse_commit_list_filtered(rev, + walken_show_commit, walken_show_object, NULL, &omitted); + + ... +---- + +Then, after your traversal, the `oidset` traversal is pretty straightforward. +Count all the objects within and modify the print statement: + +---- + /* Count the omitted objects. */ + oidset_iter_init(&omitted, &oit); + + while ((oid = oidset_iter_next(&oit))) + omitted_count++; + + printf("commits %d\nblobs %d\ntags %d\ntrees %d\nomitted %d\n", + commit_count, blob_count, tag_count, tree_count, omitted_count); +---- + +By running your walk with and without the filter, you should find that the total +object count in each case is identical. You can also time each invocation of +the `walken` subcommand, with and without `omitted` being passed in, to confirm +to yourself the runtime impact of tracking all omitted objects. + +=== Changing the Order + +Finally, let's demonstrate that you can also reorder walks of all objects, not +just walks of commits. First, we'll make our handlers chattier - modify +`walken_show_commit()` and `walken_show_object()` to print the object as they +go: + +---- +#include "hex.h" + +... + +static void walken_show_commit(struct commit *cmt, void *buf) +{ + trace_printf("commit: %s\n", oid_to_hex(&cmt->object.oid)); + commit_count++; +} + +static void walken_show_object(struct object *obj, const char *str, void *buf) +{ + trace_printf("%s: %s\n", type_name(obj->type), oid_to_hex(&obj->oid)); + + ... +} +---- + +NOTE: Since we will be examining this output directly as humans, we'll use +`trace_printf()` here. Additionally, since this change introduces a significant +number of printed lines, using `trace_printf()` will allow us to easily silence +those lines without having to recompile. + +(Leave the counter increment logic in place.) + +With only that change, run again (but save yourself some scrollback): + +---- +$ GIT_TRACE=1 ./bin-wrappers/git walken 2>&1 | head -n 10 +---- + +Take a look at the top commit with `git show` and the object ID you printed; it +should be the same as the output of `git show HEAD`. + +Next, let's change a setting on our `struct rev_info` within +`walken_object_walk()`. Find where you're changing the other settings on `rev`, +such as `rev->tree_objects` and `rev->tree_blobs_in_commit_order`, and add the +`reverse` setting at the bottom: + +---- + ... + + rev->tree_objects = 1; + rev->blob_objects = 1; + rev->tag_objects = 1; + rev->tree_blobs_in_commit_order = 1; + rev->reverse = 1; + + ... +---- + +Now, run again, but this time, let's grab the last handful of objects instead +of the first handful: + +---- +$ make +$ GIT_TRACE=1 ./bin-wrappers/git walken 2>&1 | tail -n 10 +---- + +The last commit object given should have the same OID as the one we saw at the +top before, and running `git show ` with that OID should give you again +the same results as `git show HEAD`. Furthermore, if you run and examine the +first ten lines again (with `head` instead of `tail` like we did before applying +the `reverse` setting), you should see that now the first commit printed is the +initial commit, `e83c5163`. + +== Wrapping Up + +Let's review. In this tutorial, we: + +- Built a commit walk from the ground up +- Enabled a grep filter for that commit walk +- Changed the sort order of that filtered commit walk +- Built an object walk (tags, commits, trees, and blobs) from the ground up +- Learned how to add a filter-spec to an object walk +- Changed the display order of the filtered object walk diff --git a/MyFirstObjectWalk.html b/MyFirstObjectWalk.html new file mode 100644 index 000000000..e088f094e --- /dev/null +++ b/MyFirstObjectWalk.html @@ -0,0 +1,1708 @@ + + + + + + + +My First Object Walk + + + + + + +
+
+

What’s an Object Walk?

+
+
+

The object walk is a key concept in Git - this is the process that underpins +operations like object transfer and fsck. Beginning from a given commit, the +list of objects is found by walking parent relationships between commits (commit +X based on commit W) and containment relationships between objects (tree Y is +contained within commit X, and blob Z is located within tree Y, giving our +working tree for commit X something like y/z.txt).

+
+
+

A related concept is the revision walk, which is focused on commit objects and +their parent relationships and does not delve into other object types. The +revision walk is used for operations like git log.

+
+
+ +
+
    +
  • +

    Documentation/user-manual.adoc under "Hacking Git" contains some coverage of +the revision walker in its various incarnations.

    +
  • +
  • +

    revision.h

    +
  • +
  • +

    Git for Computer Scientists +gives a good overview of the types of objects in Git and what your object +walk is really describing.

    +
  • +
+
+
+
+
+
+

Setting Up

+
+
+

Create a new branch from master.

+
+
+
+
git checkout -b revwalk origin/master
+
+
+
+

We’ll put our fiddling into a new command. For fun, let’s name it git walken. +Open up a new file builtin/walken.c and set up the command handler:

+
+
+
+
/*
+ * "git walken"
+ *
+ * Part of the "My First Object Walk" tutorial.
+ */
+
+#include "builtin.h"
+#include "trace.h"
+
+int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo)
+{
+        trace_printf(_("cmd_walken incoming...\n"));
+        return 0;
+}
+
+
+
+ + + + + +
+
Note
+
+trace_printf(), defined in trace.h, differs from printf() in +that it can be turned on or off at runtime. For the purposes of this +tutorial, we will write walken as though it is intended for use as +a "plumbing" command: that is, a command which is used primarily in +scripts, rather than interactively by humans (a "porcelain" command). +So we will send our debug output to trace_printf() instead. +When running, enable trace output by setting the environment variable GIT_TRACE. +
+
+
+

Add usage text and -h handling, like all subcommands should consistently do +(our test suite will notice and complain if you fail to do so). +We’ll need to include the parse-options.h header.

+
+
+
+
#include "parse-options.h"
+
+...
+
+int cmd_walken(int argc, const char **argv, const char *prefix)
+{
+        const char * const walken_usage[] = {
+                N_("git walken"),
+                NULL,
+        };
+        struct option options[] = {
+                OPT_END()
+        };
+
+        argc = parse_options(argc, argv, prefix, options, walken_usage, 0);
+
+        ...
+}
+
+
+
+

Also add the relevant line in builtin.h near cmd_version():

+
+
+
+
int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo);
+
+
+
+

Include the command in git.c in commands[] near the entry for version, +maintaining alphabetical ordering:

+
+
+
+
{ "walken", cmd_walken, RUN_SETUP },
+
+
+
+

Add an entry for the new command in the both the Make and Meson build system, +before the entry for worktree:

+
+
+
    +
  • +

    In the Makefile:

    +
  • +
+
+
+
+
...
+BUILTIN_OBJS += builtin/walken.o
+...
+
+
+
+
    +
  • +

    In the meson.build file:

    +
  • +
+
+
+
+
builtin_sources = [
+   ...
+  'builtin/walken.c',
+   ...
+]
+
+
+
+

Build and test out your command, without forgetting to ensure the DEVELOPER +flag is set, and with GIT_TRACE enabled so the debug output can be seen:

+
+
+
+
$ echo DEVELOPER=1 >>config.mak
+$ make
+$ GIT_TRACE=1 ./bin-wrappers/git walken
+
+
+
+ + + + + +
+
Note
+
+For a more exhaustive overview of the new command process, take a look at +Documentation/MyFirstContribution.adoc. +
+
+
+ + + + + +
+
Note
+
+A reference implementation can be found at +https://github.com/nasamuffin/git/tree/revwalk. +
+
+
+

struct rev_cmdline_info

+
+

The definition of struct rev_cmdline_info can be found in revision.h.

+
+
+

This struct is contained within the rev_info struct and is used to reflect +parameters provided by the user over the CLI.

+
+
+

nr represents the number of rev_cmdline_entry present in the array.

+
+
+

alloc is used by the ALLOC_GROW macro. Check alloc.h - this variable is +used to track the allocated size of the list.

+
+
+

Per entry, we find:

+
+
+

item is the object provided upon which to base the object walk. Items in Git +can be blobs, trees, commits, or tags. (See Documentation/gittutorial-2.adoc.)

+
+
+

name is the object ID (OID) of the object - a hex string you may be familiar +with from using Git to organize your source in the past. Check the tutorial +mentioned above towards the top for a discussion of where the OID can come +from.

+
+
+

whence indicates some information about what to do with the parents of the +specified object. We’ll explore this flag more later on; take a look at +Documentation/revisions.adoc to get an idea of what could set the whence +value.

+
+
+

flags are used to hint the beginning of the revision walk and are the first +block under the #include`s in `revision.h. The most likely ones to be set in +the rev_cmdline_info are UNINTERESTING and BOTTOM, but these same flags +can be used during the walk, as well.

+
+
+
+

struct rev_info

+
+

This one is quite a bit longer, and many fields are only used during the walk +by revision.c - not configuration options. Most of the configurable flags in +struct rev_info have a mirror in Documentation/rev-list-options.adoc. It’s a +good idea to take some time and read through that document.

+
+
+
+
+
+

Basic Commit Walk

+
+
+

First, let’s see if we can replicate the output of git log --oneline. We’ll +refer back to the implementation frequently to discover norms when performing +an object walk of our own.

+
+
+

To do so, we’ll first find all the commits, in order, which preceded the current +commit. We’ll extract the name and subject of the commit from each.

+
+
+

Ideally, we will also be able to find out which ones are currently at the tip of +various branches.

+
+
+

Setting Up

+
+

Preparing for your object walk has some distinct stages.

+
+
+
    +
  1. +

    Perform default setup for this mode, and others which may be invoked.

    +
  2. +
  3. +

    Check configuration files for relevant settings.

    +
  4. +
  5. +

    Set up the rev_info struct.

    +
  6. +
  7. +

    Tweak the initialized rev_info to suit the current walk.

    +
  8. +
  9. +

    Prepare the rev_info for the walk.

    +
  10. +
  11. +

    Iterate over the objects, processing each one.

    +
  12. +
+
+
+

Default Setups

+
+

Before examining configuration files which may modify command behavior, set up +default state for switches or options your command may have. If your command +utilizes other Git components, ask them to set up their default states as well. +For instance, git log takes advantage of grep and diff functionality, so +its init_log_defaults() sets its own state (decoration_style) and asks +grep and diff to initialize themselves by calling each of their +initialization functions.

+
+
+
+

Configuring From .gitconfig

+
+

Next, we should have a look at any relevant configuration settings (i.e., +settings readable and settable from git config). This is done by providing a +callback to repo_config(); within that callback, you can also invoke methods +from other components you may need that need to intercept these options. Your +callback will be invoked once per each configuration value which Git knows about +(global, local, worktree, etc.).

+
+
+

Similarly to the default values, we don’t have anything to do here yet +ourselves; however, we should call git_default_config() if we aren’t calling +any other existing config callbacks.

+
+
+

Add a new function to builtin/walken.c. +We’ll also need to include the config.h header:

+
+
+
+
#include "config.h"
+
+...
+
+static int git_walken_config(const char *var, const char *value,
+                             const struct config_context *ctx, void *cb)
+{
+        /*
+         * For now, we don't have any custom configuration, so fall back to
+         * the default config.
+         */
+        return git_default_config(var, value, ctx, cb);
+}
+
+
+
+

Make sure to invoke repo_config() with it in your cmd_walken():

+
+
+
+
int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo)
+{
+        ...
+
+        repo_config(repo, git_walken_config, NULL);
+
+        ...
+}
+
+
+
+
+

Setting Up rev_info

+
+

Now that we’ve gathered external configuration and options, it’s time to +initialize the rev_info object which we will use to perform the walk. This is +typically done by calling repo_init_revisions() with the repository you intend +to target, as well as the prefix argument of cmd_walken and your rev_info +struct.

+
+
+

Add the struct rev_info and the repo_init_revisions() call. +We’ll also need to include the revision.h header:

+
+
+
+
#include "revision.h"
+
+...
+
+int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo)
+{
+        /* This can go wherever you like in your declarations.*/
+        struct rev_info rev;
+        ...
+
+        /* This should go after the repo_config() call. */
+        repo_init_revisions(repo, &rev, prefix);
+
+        ...
+}
+
+
+
+
+

Tweaking rev_info For the Walk

+
+

We’re getting close, but we’re still not quite ready to go. Now that rev is +initialized, we can modify it to fit our needs. This is usually done within a +helper for clarity, so let’s add one:

+
+
+
+
static void final_rev_info_setup(struct rev_info *rev)
+{
+        /*
+         * We want to mimic the appearance of `git log --oneline`, so let's
+         * force oneline format.
+         */
+        get_commit_format("oneline", rev);
+
+        /* Start our object walk at HEAD. */
+        add_head_to_pending(rev);
+}
+
+
+
+ + + + + +
+
Note
+
+
+

Instead of using the shorthand add_head_to_pending(), you could do +something like this:

+
+
+
+
        struct setup_revision_opt opt;
+
+        memset(&opt, 0, sizeof(opt));
+        opt.def = "HEAD";
+        opt.revarg_opt = REVARG_COMMITTISH;
+        setup_revisions(argc, argv, rev, &opt);
+
+
+
+

Using a setup_revision_opt gives you finer control over your walk’s starting +point.

+
+
+
+
+

Then let’s invoke final_rev_info_setup() after the call to +repo_init_revisions():

+
+
+
+
int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo)
+{
+        ...
+
+        final_rev_info_setup(&rev);
+
+        ...
+}
+
+
+
+

Later, we may wish to add more arguments to final_rev_info_setup(). But for +now, this is all we need.

+
+
+
+

Preparing rev_info For the Walk

+
+

Now that rev is all initialized and configured, we’ve got one more setup step +before we get rolling. We can do this in a helper, which will both prepare the +rev_info for the walk, and perform the walk itself. Let’s start the helper +with the call to prepare_revision_walk(), which can return an error without +dying on its own:

+
+
+
+
static void walken_commit_walk(struct rev_info *rev)
+{
+        if (prepare_revision_walk(rev))
+                die(_("revision walk setup failed"));
+}
+
+
+
+ + + + + +
+
Note
+
+die() prints to stderr and exits the program. Since it will print to +stderr it’s likely to be seen by a human, so we will localize it. +
+
+
+
+

Performing the Walk!

+
+

Finally! We are ready to begin the walk itself. Now we can see that rev_info +can also be used as an iterator; we move to the next item in the walk by using +get_revision() repeatedly. Add the listed variable declarations at the top and +the walk loop below the prepare_revision_walk() call within your +walken_commit_walk():

+
+
+
+
#include "pretty.h"
+
+...
+
+static void walken_commit_walk(struct rev_info *rev)
+{
+        struct commit *commit;
+        struct strbuf prettybuf = STRBUF_INIT;
+
+        ...
+
+        while ((commit = get_revision(rev))) {
+                strbuf_reset(&prettybuf);
+                pp_commit_easy(CMIT_FMT_ONELINE, commit, &prettybuf);
+                puts(prettybuf.buf);
+        }
+        strbuf_release(&prettybuf);
+}
+
+
+
+ + + + + +
+
Note
+
+puts() prints a char* to stdout. Since this is the part of the +command we expect to be machine-parsed, we’re sending it directly to stdout. +
+
+
+

Give it a shot.

+
+
+
+
$ make
+$ ./bin-wrappers/git walken
+
+
+
+

You should see all of the subject lines of all the commits in +your tree’s history, in order, ending with the initial commit, "Initial revision +of "git", the information manager from hell". Congratulations! You’ve written +your first revision walk. You can play with printing some additional fields +from each commit if you’re curious; have a look at the functions available in +commit.h.

+
+
+
+
+

Adding a Filter

+
+

Next, let’s try to filter the commits we see based on their author. This is +equivalent to running git log --author=<pattern>. We can add a filter by +modifying rev_info.grep_filter, which is a struct grep_opt.

+
+
+

First some setup. Add grep_config() to git_walken_config():

+
+
+
+
static int git_walken_config(const char *var, const char *value,
+                             const struct config_context *ctx, void *cb)
+{
+        grep_config(var, value, ctx, cb);
+        return git_default_config(var, value, ctx, cb);
+}
+
+
+
+

Next, we can modify the grep_filter. This is done with convenience functions +found in grep.h. For fun, we’re filtering to only commits from folks using a +gmail.com email address - a not-very-precise guess at who may be working on +Git as a hobby. Since we’re checking the author, which is a specific line in the +header, we’ll use the append_header_grep_pattern() helper. We can use +the enum grep_header_field to indicate which part of the commit header we want +to search.

+
+
+

In final_rev_info_setup(), add your filter line:

+
+
+
+
static void final_rev_info_setup(int argc, const char **argv,
+                const char *prefix, struct rev_info *rev)
+{
+        ...
+
+        append_header_grep_pattern(&rev->grep_filter, GREP_HEADER_AUTHOR,
+                "gmail");
+        compile_grep_patterns(&rev->grep_filter);
+
+        ...
+}
+
+
+
+

append_header_grep_pattern() adds your new "gmail" pattern to rev_info, but +it won’t work unless we compile it with compile_grep_patterns().

+
+
+ + + + + +
+
Note
+
+If you are using setup_revisions() (for example, if you are passing a +setup_revision_opt instead of using add_head_to_pending()), you don’t need +to call compile_grep_patterns() because setup_revisions() calls it for you. +
+
+
+ + + + + +
+
Note
+
+We could add the same filter via the append_grep_pattern() helper if we +wanted to, but append_header_grep_pattern() adds the enum grep_context and +enum grep_pat_token for us. +
+
+
+
+

Changing the Order

+
+

There are a few ways that we can change the order of the commits during a +revision walk. Firstly, we can use the enum rev_sort_order to choose from some +typical orderings.

+
+
+

topo_order is the same as git log --topo-order: we avoid showing a parent +before all of its children have been shown, and we avoid mixing commits which +are in different lines of history. (git help log's section on --topo-order +has a very nice diagram to illustrate this.)

+
+
+

Let’s see what happens when we run with REV_SORT_BY_COMMIT_DATE as opposed to +REV_SORT_BY_AUTHOR_DATE. Add the following:

+
+
+
+
static void final_rev_info_setup(int argc, const char **argv,
+                const char *prefix, struct rev_info *rev)
+{
+        ...
+
+        rev->topo_order = 1;
+        rev->sort_order = REV_SORT_BY_COMMIT_DATE;
+
+        ...
+}
+
+
+
+

Let’s output this into a file so we can easily diff it with the walk sorted by +author date.

+
+
+
+
$ make
+$ ./bin-wrappers/git walken > commit-date.txt
+
+
+
+

Then, let’s sort by author date and run it again.

+
+
+
+
static void final_rev_info_setup(int argc, const char **argv,
+                const char *prefix, struct rev_info *rev)
+{
+        ...
+
+        rev->topo_order = 1;
+        rev->sort_order = REV_SORT_BY_AUTHOR_DATE;
+
+        ...
+}
+
+
+
+
+
$ make
+$ ./bin-wrappers/git walken > author-date.txt
+
+
+
+

Finally, compare the two. This is a little less helpful without object names or +dates, but hopefully we get the idea.

+
+
+
+
$ diff -u commit-date.txt author-date.txt
+
+
+
+

This display indicates that commits can be reordered after they’re written, for +example with git rebase.

+
+
+

Let’s try one more reordering of commits. rev_info exposes a reverse flag. +Set that flag somewhere inside of final_rev_info_setup():

+
+
+
+
static void final_rev_info_setup(int argc, const char **argv, const char *prefix,
+                struct rev_info *rev)
+{
+        ...
+
+        rev->reverse = 1;
+
+        ...
+}
+
+
+
+

Run your walk again and note the difference in order. (If you remove the grep +pattern, you should see the last commit this call gives you as your current +HEAD.)

+
+
+
+
+
+

Basic Object Walk

+
+
+

So far we’ve been walking only commits. But Git has more types of objects than +that! Let’s see if we can walk all objects, and find out some information +about each one.

+
+
+

We can base our work on an example. git pack-objects prepares all kinds of +objects for packing into a bitmap or packfile. The work we are interested in +resides in builtin/pack-objects.c:get_object_list(); examination of that +function shows that the all-object walk is being performed by +traverse_commit_list() or traverse_commit_list_filtered(). Those two +functions reside in list-objects.c; examining the source shows that, despite +the name, these functions traverse all kinds of objects. Let’s have a look at +the arguments to traverse_commit_list().

+
+
+
    +
  • +

    struct rev_info *revs: This is the rev_info used for the walk. If +its filter member is not NULL, then filter contains information for +how to filter the object list.

    +
  • +
  • +

    show_commit_fn show_commit: A callback which will be used to handle each +individual commit object.

    +
  • +
  • +

    show_object_fn show_object: A callback which will be used to handle each +non-commit object (so each blob, tree, or tag).

    +
  • +
  • +

    void *show_data: A context buffer which is passed in turn to show_commit +and show_object.

    +
  • +
+
+
+

In addition, traverse_commit_list_filtered() has an additional parameter:

+
+
+
    +
  • +

    struct oidset *omitted: A linked-list of object IDs which the provided +filter caused to be omitted.

    +
  • +
+
+
+

It looks like these methods use callbacks we provide instead of needing us +to call it repeatedly ourselves. Cool! Let’s add the callbacks first.

+
+
+

For the sake of this tutorial, we’ll simply keep track of how many of each kind +of object we find. At file scope in builtin/walken.c add the following +tracking variables:

+
+
+
+
static int commit_count;
+static int tag_count;
+static int blob_count;
+static int tree_count;
+
+
+
+

Commits are handled by a different callback than other objects; let’s do that +one first:

+
+
+
+
static void walken_show_commit(struct commit *cmt, void *buf)
+{
+        commit_count++;
+}
+
+
+
+

The cmt argument is fairly self-explanatory. But it’s worth mentioning that +the buf argument is actually the context buffer that we can provide to the +traversal calls - show_data, which we mentioned a moment ago.

+
+
+

Since we have the struct commit object, we can look at all the same parts that +we looked at in our earlier commit-only walk. For the sake of this tutorial, +though, we’ll just increment the commit counter and move on.

+
+
+

The callback for non-commits is a little different, as we’ll need to check +which kind of object we’re dealing with:

+
+
+
+
static void walken_show_object(struct object *obj, const char *str, void *buf)
+{
+        switch (obj->type) {
+        case OBJ_TREE:
+                tree_count++;
+                break;
+        case OBJ_BLOB:
+                blob_count++;
+                break;
+        case OBJ_TAG:
+                tag_count++;
+                break;
+        case OBJ_COMMIT:
+                BUG("unexpected commit object in walken_show_object\n");
+        default:
+                BUG("unexpected object type %s in walken_show_object\n",
+                        type_name(obj->type));
+        }
+}
+
+
+
+

Again, obj is fairly self-explanatory, and we can guess that buf is the same +context pointer that walken_show_commit() receives: the show_data argument +to traverse_commit_list() and traverse_commit_list_filtered(). Finally, +str contains the name of the object, which ends up being something like +foo.txt (blob), bar/baz (tree), or v1.2.3 (tag).

+
+
+

To help assure us that we aren’t double-counting commits, we’ll include some +complaining if a commit object is routed through our non-commit callback; we’ll +also complain if we see an invalid object type. Since those two cases should be +unreachable, and would only change in the event of a semantic change to the Git +codebase, we complain by using BUG() - which is a signal to a developer that +the change they made caused unintended consequences, and the rest of the +codebase needs to be updated to understand that change. BUG() is not intended +to be seen by the public, so it is not localized.

+
+
+

Our main object walk implementation is substantially different from our commit +walk implementation, so let’s make a new function to perform the object walk. We +can perform setup which is applicable to all objects here, too, to keep separate +from setup which is applicable to commit-only walks.

+
+
+

We’ll start by enabling all types of objects in the struct rev_info. We’ll +also turn on tree_blobs_in_commit_order, which means that we will walk a +commit’s tree and everything it points to immediately after we find each commit, +as opposed to waiting for the end and walking through all trees after the commit +history has been discovered. With the appropriate settings configured, we are +ready to call prepare_revision_walk().

+
+
+
+
static void walken_object_walk(struct rev_info *rev)
+{
+        rev->tree_objects = 1;
+        rev->blob_objects = 1;
+        rev->tag_objects = 1;
+        rev->tree_blobs_in_commit_order = 1;
+
+        if (prepare_revision_walk(rev))
+                die(_("revision walk setup failed"));
+
+        commit_count = 0;
+        tag_count = 0;
+        blob_count = 0;
+        tree_count = 0;
+
+
+
+

Let’s start by calling just the unfiltered walk and reporting our counts. +Complete your implementation of walken_object_walk(). +We’ll also need to include the list-objects.h header.

+
+
+
+
#include "list-objects.h"
+
+...
+
+        traverse_commit_list(rev, walken_show_commit, walken_show_object, NULL);
+
+        printf("commits %d\nblobs %d\ntags %d\ntrees %d\n", commit_count,
+                blob_count, tag_count, tree_count);
+}
+
+
+
+ + + + + +
+
Note
+
+This output is intended to be machine-parsed. Therefore, we are not +sending it to trace_printf(), and we are not localizing it - we need scripts +to be able to count on the formatting to be exactly the way it is shown here. +If we were intending this output to be read by humans, we would need to localize +it with _(). +
+
+
+

Finally, we’ll ask cmd_walken() to use the object walk instead. Discussing +command line options is out of scope for this tutorial, so we’ll just hardcode +a branch we can change at compile time. Where you call final_rev_info_setup() +and walken_commit_walk(), instead branch like so:

+
+
+
+
        if (1) {
+                add_head_to_pending(&rev);
+                walken_object_walk(&rev);
+        } else {
+                final_rev_info_setup(argc, argv, prefix, &rev);
+                walken_commit_walk(&rev);
+        }
+
+
+
+ + + + + +
+
Note
+
+For simplicity, we’ve avoided all the filters and sorts we applied in +final_rev_info_setup() and simply added HEAD to our pending queue. If you +want, you can certainly use the filters we added before by moving +final_rev_info_setup() out of the conditional and removing the call to +add_head_to_pending(). +
+
+
+

Now we can try to run our command! It should take noticeably longer than the +commit walk, but an examination of the output will give you an idea why. Your +output should look similar to this example, but with different counts:

+
+
+
+
Object walk completed. Found 55733 commits, 100274 blobs, 0 tags, and 104210 trees.
+
+
+
+

This makes sense. We have more trees than commits because the Git project has +lots of subdirectories which can change, plus at least one tree per commit. We +have no tags because we started on a commit (HEAD) and while tags can point to +commits, commits can’t point to tags.

+
+
+ + + + + +
+
Note
+
+You will have different counts when you run this yourself! The number of +objects grows along with the Git project. +
+
+
+

Adding a Filter

+
+

There are a handful of filters that we can apply to the object walk laid out in +Documentation/rev-list-options.adoc. These filters are typically useful for +operations such as creating packfiles or performing a partial clone. They are +defined in list-objects-filter-options.h. For the purposes of this tutorial we +will use the "tree:1" filter, which causes the walk to omit all trees and blobs +which are not directly referenced by commits reachable from the commit in +pending when the walk begins. (pending is the list of objects which need to +be traversed during a walk; you can imagine a breadth-first tree traversal to +help understand. In our case, that means we omit trees and blobs not directly +referenced by HEAD or HEAD's history, because we begin the walk with only +HEAD in the pending list.)

+
+
+

For now, we are not going to track the omitted objects, so we’ll replace those +parameters with NULL. For the sake of simplicity, we’ll add a simple +build-time branch to use our filter or not. Preface the line calling +traverse_commit_list() with the following, which will remind us which kind of +walk we’ve just performed:

+
+
+
+
        if (0) {
+                /* Unfiltered: */
+                trace_printf(_("Unfiltered object walk.\n"));
+        } else {
+                trace_printf(
+                        _("Filtered object walk with filterspec 'tree:1'.\n"));
+
+                parse_list_objects_filter(&rev->filter, "tree:1");
+        }
+        traverse_commit_list(rev, walken_show_commit,
+                             walken_show_object, NULL);
+
+
+
+

The rev->filter member is usually built directly from a command +line argument, so the module provides an easy way to build one from a string. +Even though we aren’t taking user input right now, we can still build one with +a hardcoded string using parse_list_objects_filter().

+
+
+

With the filter spec "tree:1", we are expecting to see only the root tree for +each commit; therefore, the tree object count should be less than or equal to +the number of commits. (For an example of why that’s true: git commit --revert +points to the same tree object as its grandparent.)

+
+
+
+

Counting Omitted Objects

+
+

We also have the capability to enumerate all objects which were omitted by a +filter, like with git log --filter=<spec> --filter-print-omitted. To do this, +change traverse_commit_list() to traverse_commit_list_filtered(), which is +able to populate an omitted list. Asking for this list of filtered objects +may cause performance degradations, however, because in this case, despite +filtering objects, the possibly much larger set of all reachable objects must +be processed in order to populate that list.

+
+
+

First, add the struct oidset and related items we will use to iterate it:

+
+
+
+
#include "oidset.h"
+
+...
+
+static void walken_object_walk(
+        ...
+
+        struct oidset omitted;
+        struct oidset_iter oit;
+        struct object_id *oid = NULL;
+        int omitted_count = 0;
+        oidset_init(&omitted, 0);
+
+        ...
+
+
+
+

Replace the call to traverse_commit_list() with +traverse_commit_list_filtered() and pass a pointer to the omitted oidset +defined and initialized above:

+
+
+
+
        ...
+
+                traverse_commit_list_filtered(rev,
+                        walken_show_commit, walken_show_object, NULL, &omitted);
+
+        ...
+
+
+
+

Then, after your traversal, the oidset traversal is pretty straightforward. +Count all the objects within and modify the print statement:

+
+
+
+
        /* Count the omitted objects. */
+        oidset_iter_init(&omitted, &oit);
+
+        while ((oid = oidset_iter_next(&oit)))
+                omitted_count++;
+
+        printf("commits %d\nblobs %d\ntags %d\ntrees %d\nomitted %d\n",
+                commit_count, blob_count, tag_count, tree_count, omitted_count);
+
+
+
+

By running your walk with and without the filter, you should find that the total +object count in each case is identical. You can also time each invocation of +the walken subcommand, with and without omitted being passed in, to confirm +to yourself the runtime impact of tracking all omitted objects.

+
+
+
+

Changing the Order

+
+

Finally, let’s demonstrate that you can also reorder walks of all objects, not +just walks of commits. First, we’ll make our handlers chattier - modify +walken_show_commit() and walken_show_object() to print the object as they +go:

+
+
+
+
#include "hex.h"
+
+...
+
+static void walken_show_commit(struct commit *cmt, void *buf)
+{
+        trace_printf("commit: %s\n", oid_to_hex(&cmt->object.oid));
+        commit_count++;
+}
+
+static void walken_show_object(struct object *obj, const char *str, void *buf)
+{
+        trace_printf("%s: %s\n", type_name(obj->type), oid_to_hex(&obj->oid));
+
+        ...
+}
+
+
+
+ + + + + +
+
Note
+
+Since we will be examining this output directly as humans, we’ll use +trace_printf() here. Additionally, since this change introduces a significant +number of printed lines, using trace_printf() will allow us to easily silence +those lines without having to recompile. +
+
+
+

(Leave the counter increment logic in place.)

+
+
+

With only that change, run again (but save yourself some scrollback):

+
+
+
+
$ GIT_TRACE=1 ./bin-wrappers/git walken 2>&1 | head -n 10
+
+
+
+

Take a look at the top commit with git show and the object ID you printed; it +should be the same as the output of git show HEAD.

+
+
+

Next, let’s change a setting on our struct rev_info within +walken_object_walk(). Find where you’re changing the other settings on rev, +such as rev->tree_objects and rev->tree_blobs_in_commit_order, and add the +reverse setting at the bottom:

+
+
+
+
        ...
+
+        rev->tree_objects = 1;
+        rev->blob_objects = 1;
+        rev->tag_objects = 1;
+        rev->tree_blobs_in_commit_order = 1;
+        rev->reverse = 1;
+
+        ...
+
+
+
+

Now, run again, but this time, let’s grab the last handful of objects instead +of the first handful:

+
+
+
+
$ make
+$ GIT_TRACE=1 ./bin-wrappers/git walken 2>&1 | tail -n 10
+
+
+
+

The last commit object given should have the same OID as the one we saw at the +top before, and running git show <oid> with that OID should give you again +the same results as git show HEAD. Furthermore, if you run and examine the +first ten lines again (with head instead of tail like we did before applying +the reverse setting), you should see that now the first commit printed is the +initial commit, e83c5163.

+
+
+
+
+
+

Wrapping Up

+
+
+

Let’s review. In this tutorial, we:

+
+
+
    +
  • +

    Built a commit walk from the ground up

    +
  • +
  • +

    Enabled a grep filter for that commit walk

    +
  • +
  • +

    Changed the sort order of that filtered commit walk

    +
  • +
  • +

    Built an object walk (tags, commits, trees, and blobs) from the ground up

    +
  • +
  • +

    Learned how to add a filter-spec to an object walk

    +
  • +
  • +

    Changed the display order of the filtered object walk

    +
  • +
+
+
+
+
+ + + \ No newline at end of file diff --git a/RelNotes/1.5.0.1.txt b/RelNotes/1.5.0.1.adoc similarity index 100% rename from RelNotes/1.5.0.1.txt rename to RelNotes/1.5.0.1.adoc diff --git a/RelNotes/1.5.0.2.txt b/RelNotes/1.5.0.2.adoc similarity index 100% rename from RelNotes/1.5.0.2.txt rename to RelNotes/1.5.0.2.adoc diff --git a/RelNotes/1.5.0.3.txt b/RelNotes/1.5.0.3.adoc similarity index 100% rename from RelNotes/1.5.0.3.txt rename to RelNotes/1.5.0.3.adoc diff --git a/RelNotes/1.5.0.4.txt b/RelNotes/1.5.0.4.adoc similarity index 100% rename from RelNotes/1.5.0.4.txt rename to RelNotes/1.5.0.4.adoc diff --git a/RelNotes/1.5.0.5.txt b/RelNotes/1.5.0.5.adoc similarity index 100% rename from RelNotes/1.5.0.5.txt rename to RelNotes/1.5.0.5.adoc diff --git a/RelNotes/1.5.0.6.txt b/RelNotes/1.5.0.6.adoc similarity index 100% rename from RelNotes/1.5.0.6.txt rename to RelNotes/1.5.0.6.adoc diff --git a/RelNotes/1.5.0.7.txt b/RelNotes/1.5.0.7.adoc similarity index 100% rename from RelNotes/1.5.0.7.txt rename to RelNotes/1.5.0.7.adoc diff --git a/RelNotes/1.5.0.adoc b/RelNotes/1.5.0.adoc new file mode 100644 index 000000000..d6d42f318 --- /dev/null +++ b/RelNotes/1.5.0.adoc @@ -0,0 +1,469 @@ +GIT v1.5.0 Release Notes +======================== + +Old news +-------- + +This section is for people who are upgrading from ancient +versions of git. Although all of the changes in this section +happened before the current v1.4.4 release, they are summarized +here in the v1.5.0 release notes for people who skipped earlier +versions. + +As of git v1.5.0 there are some optional features that changes +the repository to allow data to be stored and transferred more +efficiently. These features are not enabled by default, as they +will make the repository unusable with older versions of git. +Specifically, the available options are: + + - There is a configuration variable core.legacyheaders that + changes the format of loose objects so that they are more + efficient to pack and to send out of the repository over git + native protocol, since v1.4.2. However, loose objects + written in the new format cannot be read by git older than + that version; people fetching from your repository using + older clients over dumb transports (e.g. http) using older + versions of git will also be affected. + + To let git use the new loose object format, you have to + set core.legacyheaders to false. + + - Since v1.4.3, configuration repack.usedeltabaseoffset allows + packfile to be created in more space efficient format, which + cannot be read by git older than that version. + + To let git use the new format for packfiles, you have to + set repack.usedeltabaseoffset to true. + +The above two new features are not enabled by default and you +have to explicitly ask for them, because they make repositories +unreadable by older versions of git, and in v1.5.0 we still do +not enable them by default for the same reason. We will change +this default probably 1 year after 1.4.2's release, when it is +reasonable to expect everybody to have new enough version of +git. + + - 'git pack-refs' appeared in v1.4.4; this command allows tags + to be accessed much more efficiently than the traditional + 'one-file-per-tag' format. Older git-native clients can + still fetch from a repository that packed and pruned refs + (the server side needs to run the up-to-date version of git), + but older dumb transports cannot. Packing of refs is done by + an explicit user action, either by use of "git pack-refs + --prune" command or by use of "git gc" command. + + - 'git -p' to paginate anything -- many commands do pagination + by default on a tty. Introduced between v1.4.1 and v1.4.2; + this may surprise old timers. + + - 'git archive' superseded 'git tar-tree' in v1.4.3; + + - 'git cvsserver' was new invention in v1.3.0; + + - 'git repo-config', 'git grep', 'git rebase' and 'gitk' were + seriously enhanced during v1.4.0 timeperiod. + + - 'gitweb' became part of git.git during v1.4.0 timeperiod and + seriously modified since then. + + - reflog is an v1.4.0 invention. This allows you to name a + revision that a branch used to be at (e.g. "git diff + master@{yesterday} master" allows you to see changes since + yesterday's tip of the branch). + + +Updates in v1.5.0 since v1.4.4 series +------------------------------------- + +* Index manipulation + + - git-add is to add contents to the index (aka "staging area" + for the next commit), whether the file the contents happen to + be is an existing one or a newly created one. + + - git-add without any argument does not add everything + anymore. Use 'git-add .' instead. Also you can add + otherwise ignored files with an -f option. + + - git-add tries to be more friendly to users by offering an + interactive mode ("git-add -i"). + + - git-commit used to refuse to commit if was + different between HEAD and the index (i.e. update-index was + used on it earlier). This check was removed. + + - git-rm is much saner and safer. It is used to remove paths + from both the index file and the working tree, and makes sure + you are not losing any local modification before doing so. + + - git-reset ... can be used to revert index + entries for selected paths. + + - git-update-index is much less visible. Many suggestions to + use the command in git output and documentation have now been + replaced by simpler commands such as "git add" or "git rm". + + +* Repository layout and objects transfer + + - The data for origin repository is stored in the configuration + file $GIT_DIR/config, not in $GIT_DIR/remotes/, for newly + created clones. The latter is still supported and there is + no need to convert your existing repository if you are + already comfortable with your workflow with the layout. + + - git-clone always uses what is known as "separate remote" + layout for a newly created repository with a working tree. + + A repository with the separate remote layout starts with only + one default branch, 'master', to be used for your own + development. Unlike the traditional layout that copied all + the upstream branches into your branch namespace (while + renaming their 'master' to your 'origin'), the new layout + puts upstream branches into local "remote-tracking branches" + with their own namespace. These can be referenced with names + such as "origin/$upstream_branch_name" and are stored in + .git/refs/remotes rather than .git/refs/heads where normal + branches are stored. + + This layout keeps your own branch namespace less cluttered, + avoids name collision with your upstream, makes it possible + to automatically track new branches created at the remote + after you clone from it, and makes it easier to interact with + more than one remote repository (you can use "git remote" to + add other repositories to track). There might be some + surprises: + + * 'git branch' does not show the remote tracking branches. + It only lists your own branches. Use '-r' option to view + the tracking branches. + + * If you are forking off of a branch obtained from the + upstream, you would have done something like 'git branch + my-next next', because traditional layout dropped the + tracking branch 'next' into your own branch namespace. + With the separate remote layout, you say 'git branch next + origin/next', which allows you to use the matching name + 'next' for your own branch. It also allows you to track a + remote other than 'origin' (i.e. where you initially cloned + from) and fork off of a branch from there the same way + (e.g. "git branch mingw j6t/master"). + + Repositories initialized with the traditional layout continue + to work. + + - New branches that appear on the origin side after a clone is + made are also tracked automatically. This is done with an + wildcard refspec "refs/heads/*:refs/remotes/origin/*", which + older git does not understand, so if you clone with 1.5.0, + you would need to downgrade remote.*.fetch in the + configuration file to specify each branch you are interested + in individually if you plan to fetch into the repository with + older versions of git (but why would you?). + + - Similarly, wildcard refspec "refs/heads/*:refs/remotes/me/*" + can be given to "git-push" command to update the tracking + branches that is used to track the repository you are pushing + from on the remote side. + + - git-branch and git-show-branch know remote tracking branches + (use the command line switch "-r" to list only tracked branches). + + - git-push can now be used to delete a remote branch or a tag. + This requires the updated git on the remote side (use "git + push :refs/heads/" to delete "branch"). + + - git-push more aggressively keeps the transferred objects + packed. Earlier we recommended to monitor amount of loose + objects and repack regularly, but you should repack when you + accumulated too many small packs this way as well. Updated + git-count-objects helps you with this. + + - git-fetch also more aggressively keeps the transferred objects + packed. This behavior of git-push and git-fetch can be + tweaked with a single configuration transfer.unpacklimit (but + usually there should not be any need for a user to tweak it). + + - A new command, git-remote, can help you manage your remote + tracking branch definitions. + + - You may need to specify explicit paths for upload-pack and/or + receive-pack due to your ssh daemon configuration on the + other end. This can now be done via remote.*.uploadpack and + remote.*.receivepack configuration. + + +* Bare repositories + + - Certain commands change their behavior in a bare repository + (i.e. a repository without associated working tree). We use + a fairly conservative heuristic (if $GIT_DIR is ".git", or + ends with "/.git", the repository is not bare) to decide if a + repository is bare, but "core.bare" configuration variable + can be used to override the heuristic when it misidentifies + your repository. + + - git-fetch used to complain updating the current branch but + this is now allowed for a bare repository. So is the use of + 'git-branch -f' to update the current branch. + + - Porcelain-ish commands that require a working tree refuses to + work in a bare repository. + + +* Reflog + + - Reflog records the history from the view point of the local + repository. In other words, regardless of the real history, + the reflog shows the history as seen by one particular + repository (this enables you to ask "what was the current + revision in _this_ repository, yesterday at 1pm?"). This + facility is enabled by default for repositories with working + trees, and can be accessed with the "branch@{time}" and + "branch@{Nth}" notation. + + - "git show-branch" learned showing the reflog data with the + new -g option. "git log" has -g option to view reflog + entries in a more verbose manner. + + - git-branch knows how to rename branches and moves existing + reflog data from the old branch to the new one. + + - In addition to the reflog support in v1.4.4 series, HEAD + reference maintains its own log. "HEAD@{5.minutes.ago}" + means the commit you were at 5 minutes ago, which takes + branch switching into account. If you want to know where the + tip of your current branch was at 5 minutes ago, you need to + explicitly say its name (e.g. "master@{5.minutes.ago}") or + omit the refname altogether i.e. "@{5.minutes.ago}". + + - The commits referred to by reflog entries are now protected + against pruning. The new command "git reflog expire" can be + used to truncate older reflog entries and entries that refer + to commits that have been pruned away previously with older + versions of git. + + Existing repositories that have been using reflog may get + complaints from fsck-objects and may not be able to run + git-repack, if you had run git-prune from older git; please + run "git reflog expire --stale-fix --all" first to remove + reflog entries that refer to commits that are no longer in + the repository when that happens. + + +* Cruft removal + + - We used to say "old commits are retrievable using reflog and + 'master@{yesterday}' syntax as long as you haven't run + git-prune". We no longer have to say the latter half of the + above sentence, as git-prune does not remove things reachable + from reflog entries. + + - There is a toplevel garbage collector script, 'git-gc', that + runs periodic cleanup functions, including 'git-repack -a -d', + 'git-reflog expire', 'git-pack-refs --prune', and 'git-rerere + gc'. + + - The output from fsck ("fsck-objects" is called just "fsck" + now, but the old name continues to work) was needlessly + alarming in that it warned missing objects that are reachable + only from dangling objects. This has been corrected and the + output is much more useful. + + +* Detached HEAD + + - You can use 'git-checkout' to check out an arbitrary revision + or a tag as well, instead of named branches. This will + dissociate your HEAD from the branch you are currently on. + + A typical use of this feature is to "look around". E.g. + + $ git checkout v2.6.16 + ... compile, test, etc. + $ git checkout v2.6.17 + ... compile, test, etc. + + - After detaching your HEAD, you can go back to an existing + branch with usual "git checkout $branch". Also you can + start a new branch using "git checkout -b $newbranch" to + start a new branch at that commit. + + - You can even pull from other repositories, make merges and + commits while your HEAD is detached. Also you can use "git + reset" to jump to arbitrary commit, while still keeping your + HEAD detached. + + Remember that a detached state is volatile, i.e. it will be forgotten + as soon as you move away from it with the checkout or reset command, + unless a branch is created from it as mentioned above. It is also + possible to rescue a lost detached state from the HEAD reflog. + + +* Packed refs + + - Repositories with hundreds of tags have been paying large + overhead, both in storage and in runtime, due to the + traditional one-ref-per-file format. A new command, + git-pack-refs, can be used to "pack" them in more efficient + representation (you can let git-gc do this for you). + + - Clones and fetches over dumb transports are now aware of + packed refs and can download from repositories that use + them. + + +* Configuration + + - configuration related to color setting are consolidated under + color.* namespace (older diff.color.*, status.color.* are + still supported). + + - 'git-repo-config' command is accessible as 'git-config' now. + + +* Updated features + + - git-describe uses better criteria to pick a base ref. It + used to pick the one with the newest timestamp, but now it + picks the one that is topologically the closest (that is, + among ancestors of commit C, the ref T that has the shortest + output from "git-rev-list T..C" is chosen). + + - git-describe gives the number of commits since the base ref + between the refname and the hash suffix. E.g. the commit one + before v2.6.20-rc6 in the kernel repository is: + + v2.6.20-rc5-306-ga21b069 + + which tells you that its object name begins with a21b069, + v2.6.20-rc5 is an ancestor of it (meaning, the commit + contains everything -rc5 has), and there are 306 commits + since v2.6.20-rc5. + + - git-describe with --abbrev=0 can be used to show only the + name of the base ref. + + - git-blame learned a new option, --incremental, that tells it + to output the blames as they are assigned. A sample script + to use it is also included as contrib/blameview. + + - git-blame starts annotating from the working tree by default. + + +* Less external dependency + + - We no longer require the "merge" program from the RCS suite. + All 3-way file-level merges are now done internally. + + - The original implementation of git-merge-recursive which was + in Python has been removed; we have a C implementation of it + now. + + - git-shortlog is no longer a Perl script. It no longer + requires output piped from git-log; it can accept revision + parameters directly on the command line. + + +* I18n + + - We have always encouraged the commit message to be encoded in + UTF-8, but the users are allowed to use legacy encoding as + appropriate for their projects. This will continue to be the + case. However, a non UTF-8 commit encoding _must_ be + explicitly set with i18n.commitencoding in the repository + where a commit is made; otherwise git-commit-tree will + complain if the log message does not look like a valid UTF-8 + string. + + - The value of i18n.commitencoding in the originating + repository is recorded in the commit object on the "encoding" + header, if it is not UTF-8. git-log and friends notice this, + and re-encodes the message to the log output encoding when + displaying, if they are different. The log output encoding + is determined by "git log --encoding=", + i18n.logoutputencoding configuration, or i18n.commitencoding + configuration, in the decreasing order of preference, and + defaults to UTF-8. + + - Tools for e-mailed patch application now default to -u + behavior; i.e. it always re-codes from the e-mailed encoding + to the encoding specified with i18n.commitencoding. This + unfortunately forces projects that have happily been using a + legacy encoding without setting i18n.commitencoding to set + the configuration, but taken with other improvement, please + excuse us for this very minor one-time inconvenience. + + +* e-mailed patches + + - See the above I18n section. + + - git-format-patch now enables --binary without being asked. + git-am does _not_ default to it, as sending binary patch via + e-mail is unusual and is harder to review than textual + patches and it is prudent to require the person who is + applying the patch to explicitly ask for it. + + - The default suffix for git-format-patch output is now ".patch", + not ".txt". This can be changed with --suffix=.txt option, + or setting the config variable "format.suffix" to ".txt". + + +* Foreign SCM interfaces + + - git-svn now requires the Perl SVN:: libraries, the + command-line backend was too slow and limited. + + - the 'commit' subcommand of git-svn has been renamed to + 'set-tree', and 'dcommit' is the recommended replacement for + day-to-day work. + + - git fast-import backend. + + +* User support + + - Quite a lot of documentation updates. + + - Bash completion scripts have been updated heavily. + + - Better error messages for often used Porcelainish commands. + + - Git GUI. This is a simple Tk based graphical interface for + common Git operations. + + +* Sliding mmap + + - We used to assume that we can mmap the whole packfile while + in use, but with a large project this consumes huge virtual + memory space and truly huge ones would not fit in the + userland address space on 32-bit platforms. We now mmap huge + packfile in pieces to avoid this problem. + + +* Shallow clones + + - There is a partial support for 'shallow' repositories that + keeps only recent history. A 'shallow clone' is created by + specifying how deep that truncated history should be + (e.g. "git clone --depth 5 git://some.where/repo.git"). + + Currently a shallow repository has number of limitations: + + - Cloning and fetching _from_ a shallow clone are not + supported (nor tested -- so they might work by accident but + they are not expected to). + + - Pushing from nor into a shallow clone are not expected to + work. + + - Merging inside a shallow repository would work as long as a + merge base is found in the recent history, but otherwise it + will be like merging unrelated histories and may result in + huge conflicts. + + but this would be more than adequate for people who want to + look at near the tip of a big project with a deep history and + send patches in e-mail format. diff --git a/RelNotes/1.5.0.txt b/RelNotes/1.5.0.txt deleted file mode 100644 index daf4bdb0d..000000000 --- a/RelNotes/1.5.0.txt +++ /dev/null @@ -1,469 +0,0 @@ -GIT v1.5.0 Release Notes -======================== - -Old news --------- - -This section is for people who are upgrading from ancient -versions of git. Although all of the changes in this section -happened before the current v1.4.4 release, they are summarized -here in the v1.5.0 release notes for people who skipped earlier -versions. - -As of git v1.5.0 there are some optional features that changes -the repository to allow data to be stored and transferred more -efficiently. These features are not enabled by default, as they -will make the repository unusable with older versions of git. -Specifically, the available options are: - - - There is a configuration variable core.legacyheaders that - changes the format of loose objects so that they are more - efficient to pack and to send out of the repository over git - native protocol, since v1.4.2. However, loose objects - written in the new format cannot be read by git older than - that version; people fetching from your repository using - older clients over dumb transports (e.g. http) using older - versions of git will also be affected. - - To let git use the new loose object format, you have to - set core.legacyheaders to false. - - - Since v1.4.3, configuration repack.usedeltabaseoffset allows - packfile to be created in more space efficient format, which - cannot be read by git older than that version. - - To let git use the new format for packfiles, you have to - set repack.usedeltabaseoffset to true. - -The above two new features are not enabled by default and you -have to explicitly ask for them, because they make repositories -unreadable by older versions of git, and in v1.5.0 we still do -not enable them by default for the same reason. We will change -this default probably 1 year after 1.4.2's release, when it is -reasonable to expect everybody to have new enough version of -git. - - - 'git pack-refs' appeared in v1.4.4; this command allows tags - to be accessed much more efficiently than the traditional - 'one-file-per-tag' format. Older git-native clients can - still fetch from a repository that packed and pruned refs - (the server side needs to run the up-to-date version of git), - but older dumb transports cannot. Packing of refs is done by - an explicit user action, either by use of "git pack-refs - --prune" command or by use of "git gc" command. - - - 'git -p' to paginate anything -- many commands do pagination - by default on a tty. Introduced between v1.4.1 and v1.4.2; - this may surprise old timers. - - - 'git archive' superseded 'git tar-tree' in v1.4.3; - - - 'git cvsserver' was new invention in v1.3.0; - - - 'git repo-config', 'git grep', 'git rebase' and 'gitk' were - seriously enhanced during v1.4.0 timeperiod. - - - 'gitweb' became part of git.git during v1.4.0 timeperiod and - seriously modified since then. - - - reflog is an v1.4.0 invention. This allows you to name a - revision that a branch used to be at (e.g. "git diff - master@{yesterday} master" allows you to see changes since - yesterday's tip of the branch). - - -Updates in v1.5.0 since v1.4.4 series -------------------------------------- - -* Index manipulation - - - git-add is to add contents to the index (aka "staging area" - for the next commit), whether the file the contents happen to - be is an existing one or a newly created one. - - - git-add without any argument does not add everything - anymore. Use 'git-add .' instead. Also you can add - otherwise ignored files with an -f option. - - - git-add tries to be more friendly to users by offering an - interactive mode ("git-add -i"). - - - git-commit used to refuse to commit if was - different between HEAD and the index (i.e. update-index was - used on it earlier). This check was removed. - - - git-rm is much saner and safer. It is used to remove paths - from both the index file and the working tree, and makes sure - you are not losing any local modification before doing so. - - - git-reset ... can be used to revert index - entries for selected paths. - - - git-update-index is much less visible. Many suggestions to - use the command in git output and documentation have now been - replaced by simpler commands such as "git add" or "git rm". - - -* Repository layout and objects transfer - - - The data for origin repository is stored in the configuration - file $GIT_DIR/config, not in $GIT_DIR/remotes/, for newly - created clones. The latter is still supported and there is - no need to convert your existing repository if you are - already comfortable with your workflow with the layout. - - - git-clone always uses what is known as "separate remote" - layout for a newly created repository with a working tree. - - A repository with the separate remote layout starts with only - one default branch, 'master', to be used for your own - development. Unlike the traditional layout that copied all - the upstream branches into your branch namespace (while - renaming their 'master' to your 'origin'), the new layout - puts upstream branches into local "remote-tracking branches" - with their own namespace. These can be referenced with names - such as "origin/$upstream_branch_name" and are stored in - .git/refs/remotes rather than .git/refs/heads where normal - branches are stored. - - This layout keeps your own branch namespace less cluttered, - avoids name collision with your upstream, makes it possible - to automatically track new branches created at the remote - after you clone from it, and makes it easier to interact with - more than one remote repository (you can use "git remote" to - add other repositories to track). There might be some - surprises: - - * 'git branch' does not show the remote tracking branches. - It only lists your own branches. Use '-r' option to view - the tracking branches. - - * If you are forking off of a branch obtained from the - upstream, you would have done something like 'git branch - my-next next', because traditional layout dropped the - tracking branch 'next' into your own branch namespace. - With the separate remote layout, you say 'git branch next - origin/next', which allows you to use the matching name - 'next' for your own branch. It also allows you to track a - remote other than 'origin' (i.e. where you initially cloned - from) and fork off of a branch from there the same way - (e.g. "git branch mingw j6t/master"). - - Repositories initialized with the traditional layout continue - to work. - - - New branches that appear on the origin side after a clone is - made are also tracked automatically. This is done with an - wildcard refspec "refs/heads/*:refs/remotes/origin/*", which - older git does not understand, so if you clone with 1.5.0, - you would need to downgrade remote.*.fetch in the - configuration file to specify each branch you are interested - in individually if you plan to fetch into the repository with - older versions of git (but why would you?). - - - Similarly, wildcard refspec "refs/heads/*:refs/remotes/me/*" - can be given to "git-push" command to update the tracking - branches that is used to track the repository you are pushing - from on the remote side. - - - git-branch and git-show-branch know remote tracking branches - (use the command line switch "-r" to list only tracked branches). - - - git-push can now be used to delete a remote branch or a tag. - This requires the updated git on the remote side (use "git - push :refs/heads/" to delete "branch"). - - - git-push more aggressively keeps the transferred objects - packed. Earlier we recommended to monitor amount of loose - objects and repack regularly, but you should repack when you - accumulated too many small packs this way as well. Updated - git-count-objects helps you with this. - - - git-fetch also more aggressively keeps the transferred objects - packed. This behavior of git-push and git-fetch can be - tweaked with a single configuration transfer.unpacklimit (but - usually there should not be any need for a user to tweak it). - - - A new command, git-remote, can help you manage your remote - tracking branch definitions. - - - You may need to specify explicit paths for upload-pack and/or - receive-pack due to your ssh daemon configuration on the - other end. This can now be done via remote.*.uploadpack and - remote.*.receivepack configuration. - - -* Bare repositories - - - Certain commands change their behavior in a bare repository - (i.e. a repository without associated working tree). We use - a fairly conservative heuristic (if $GIT_DIR is ".git", or - ends with "/.git", the repository is not bare) to decide if a - repository is bare, but "core.bare" configuration variable - can be used to override the heuristic when it misidentifies - your repository. - - - git-fetch used to complain updating the current branch but - this is now allowed for a bare repository. So is the use of - 'git-branch -f' to update the current branch. - - - Porcelain-ish commands that require a working tree refuses to - work in a bare repository. - - -* Reflog - - - Reflog records the history from the view point of the local - repository. In other words, regardless of the real history, - the reflog shows the history as seen by one particular - repository (this enables you to ask "what was the current - revision in _this_ repository, yesterday at 1pm?"). This - facility is enabled by default for repositories with working - trees, and can be accessed with the "branch@{time}" and - "branch@{Nth}" notation. - - - "git show-branch" learned showing the reflog data with the - new -g option. "git log" has -g option to view reflog - entries in a more verbose manner. - - - git-branch knows how to rename branches and moves existing - reflog data from the old branch to the new one. - - - In addition to the reflog support in v1.4.4 series, HEAD - reference maintains its own log. "HEAD@{5.minutes.ago}" - means the commit you were at 5 minutes ago, which takes - branch switching into account. If you want to know where the - tip of your current branch was at 5 minutes ago, you need to - explicitly say its name (e.g. "master@{5.minutes.ago}") or - omit the refname altogether i.e. "@{5.minutes.ago}". - - - The commits referred to by reflog entries are now protected - against pruning. The new command "git reflog expire" can be - used to truncate older reflog entries and entries that refer - to commits that have been pruned away previously with older - versions of git. - - Existing repositories that have been using reflog may get - complaints from fsck-objects and may not be able to run - git-repack, if you had run git-prune from older git; please - run "git reflog expire --stale-fix --all" first to remove - reflog entries that refer to commits that are no longer in - the repository when that happens. - - -* Crufts removal - - - We used to say "old commits are retrievable using reflog and - 'master@{yesterday}' syntax as long as you haven't run - git-prune". We no longer have to say the latter half of the - above sentence, as git-prune does not remove things reachable - from reflog entries. - - - There is a toplevel garbage collector script, 'git-gc', that - runs periodic cleanup functions, including 'git-repack -a -d', - 'git-reflog expire', 'git-pack-refs --prune', and 'git-rerere - gc'. - - - The output from fsck ("fsck-objects" is called just "fsck" - now, but the old name continues to work) was needlessly - alarming in that it warned missing objects that are reachable - only from dangling objects. This has been corrected and the - output is much more useful. - - -* Detached HEAD - - - You can use 'git-checkout' to check out an arbitrary revision - or a tag as well, instead of named branches. This will - dissociate your HEAD from the branch you are currently on. - - A typical use of this feature is to "look around". E.g. - - $ git checkout v2.6.16 - ... compile, test, etc. - $ git checkout v2.6.17 - ... compile, test, etc. - - - After detaching your HEAD, you can go back to an existing - branch with usual "git checkout $branch". Also you can - start a new branch using "git checkout -b $newbranch" to - start a new branch at that commit. - - - You can even pull from other repositories, make merges and - commits while your HEAD is detached. Also you can use "git - reset" to jump to arbitrary commit, while still keeping your - HEAD detached. - - Remember that a detached state is volatile, i.e. it will be forgotten - as soon as you move away from it with the checkout or reset command, - unless a branch is created from it as mentioned above. It is also - possible to rescue a lost detached state from the HEAD reflog. - - -* Packed refs - - - Repositories with hundreds of tags have been paying large - overhead, both in storage and in runtime, due to the - traditional one-ref-per-file format. A new command, - git-pack-refs, can be used to "pack" them in more efficient - representation (you can let git-gc do this for you). - - - Clones and fetches over dumb transports are now aware of - packed refs and can download from repositories that use - them. - - -* Configuration - - - configuration related to color setting are consolidated under - color.* namespace (older diff.color.*, status.color.* are - still supported). - - - 'git-repo-config' command is accessible as 'git-config' now. - - -* Updated features - - - git-describe uses better criteria to pick a base ref. It - used to pick the one with the newest timestamp, but now it - picks the one that is topologically the closest (that is, - among ancestors of commit C, the ref T that has the shortest - output from "git-rev-list T..C" is chosen). - - - git-describe gives the number of commits since the base ref - between the refname and the hash suffix. E.g. the commit one - before v2.6.20-rc6 in the kernel repository is: - - v2.6.20-rc5-306-ga21b069 - - which tells you that its object name begins with a21b069, - v2.6.20-rc5 is an ancestor of it (meaning, the commit - contains everything -rc5 has), and there are 306 commits - since v2.6.20-rc5. - - - git-describe with --abbrev=0 can be used to show only the - name of the base ref. - - - git-blame learned a new option, --incremental, that tells it - to output the blames as they are assigned. A sample script - to use it is also included as contrib/blameview. - - - git-blame starts annotating from the working tree by default. - - -* Less external dependency - - - We no longer require the "merge" program from the RCS suite. - All 3-way file-level merges are now done internally. - - - The original implementation of git-merge-recursive which was - in Python has been removed; we have a C implementation of it - now. - - - git-shortlog is no longer a Perl script. It no longer - requires output piped from git-log; it can accept revision - parameters directly on the command line. - - -* I18n - - - We have always encouraged the commit message to be encoded in - UTF-8, but the users are allowed to use legacy encoding as - appropriate for their projects. This will continue to be the - case. However, a non UTF-8 commit encoding _must_ be - explicitly set with i18n.commitencoding in the repository - where a commit is made; otherwise git-commit-tree will - complain if the log message does not look like a valid UTF-8 - string. - - - The value of i18n.commitencoding in the originating - repository is recorded in the commit object on the "encoding" - header, if it is not UTF-8. git-log and friends notice this, - and reencodes the message to the log output encoding when - displaying, if they are different. The log output encoding - is determined by "git log --encoding=", - i18n.logoutputencoding configuration, or i18n.commitencoding - configuration, in the decreasing order of preference, and - defaults to UTF-8. - - - Tools for e-mailed patch application now default to -u - behavior; i.e. it always re-codes from the e-mailed encoding - to the encoding specified with i18n.commitencoding. This - unfortunately forces projects that have happily been using a - legacy encoding without setting i18n.commitencoding to set - the configuration, but taken with other improvement, please - excuse us for this very minor one-time inconvenience. - - -* e-mailed patches - - - See the above I18n section. - - - git-format-patch now enables --binary without being asked. - git-am does _not_ default to it, as sending binary patch via - e-mail is unusual and is harder to review than textual - patches and it is prudent to require the person who is - applying the patch to explicitly ask for it. - - - The default suffix for git-format-patch output is now ".patch", - not ".txt". This can be changed with --suffix=.txt option, - or setting the config variable "format.suffix" to ".txt". - - -* Foreign SCM interfaces - - - git-svn now requires the Perl SVN:: libraries, the - command-line backend was too slow and limited. - - - the 'commit' subcommand of git-svn has been renamed to - 'set-tree', and 'dcommit' is the recommended replacement for - day-to-day work. - - - git fast-import backend. - - -* User support - - - Quite a lot of documentation updates. - - - Bash completion scripts have been updated heavily. - - - Better error messages for often used Porcelainish commands. - - - Git GUI. This is a simple Tk based graphical interface for - common Git operations. - - -* Sliding mmap - - - We used to assume that we can mmap the whole packfile while - in use, but with a large project this consumes huge virtual - memory space and truly huge ones would not fit in the - userland address space on 32-bit platforms. We now mmap huge - packfile in pieces to avoid this problem. - - -* Shallow clones - - - There is a partial support for 'shallow' repositories that - keeps only recent history. A 'shallow clone' is created by - specifying how deep that truncated history should be - (e.g. "git clone --depth 5 git://some.where/repo.git"). - - Currently a shallow repository has number of limitations: - - - Cloning and fetching _from_ a shallow clone are not - supported (nor tested -- so they might work by accident but - they are not expected to). - - - Pushing from nor into a shallow clone are not expected to - work. - - - Merging inside a shallow repository would work as long as a - merge base is found in the recent history, but otherwise it - will be like merging unrelated histories and may result in - huge conflicts. - - but this would be more than adequate for people who want to - look at near the tip of a big project with a deep history and - send patches in e-mail format. diff --git a/RelNotes/1.5.1.1.txt b/RelNotes/1.5.1.1.adoc similarity index 100% rename from RelNotes/1.5.1.1.txt rename to RelNotes/1.5.1.1.adoc diff --git a/RelNotes/1.5.1.2.txt b/RelNotes/1.5.1.2.adoc similarity index 100% rename from RelNotes/1.5.1.2.txt rename to RelNotes/1.5.1.2.adoc diff --git a/RelNotes/1.5.1.3.txt b/RelNotes/1.5.1.3.adoc similarity index 100% rename from RelNotes/1.5.1.3.txt rename to RelNotes/1.5.1.3.adoc diff --git a/RelNotes/1.5.1.4.txt b/RelNotes/1.5.1.4.adoc similarity index 100% rename from RelNotes/1.5.1.4.txt rename to RelNotes/1.5.1.4.adoc diff --git a/RelNotes/1.5.1.5.txt b/RelNotes/1.5.1.5.adoc similarity index 100% rename from RelNotes/1.5.1.5.txt rename to RelNotes/1.5.1.5.adoc diff --git a/RelNotes/1.5.1.6.txt b/RelNotes/1.5.1.6.adoc similarity index 100% rename from RelNotes/1.5.1.6.txt rename to RelNotes/1.5.1.6.adoc diff --git a/RelNotes/1.5.1.txt b/RelNotes/1.5.1.adoc similarity index 100% rename from RelNotes/1.5.1.txt rename to RelNotes/1.5.1.adoc diff --git a/RelNotes/1.5.2.1.txt b/RelNotes/1.5.2.1.adoc similarity index 100% rename from RelNotes/1.5.2.1.txt rename to RelNotes/1.5.2.1.adoc diff --git a/RelNotes/1.5.2.2.txt b/RelNotes/1.5.2.2.adoc similarity index 100% rename from RelNotes/1.5.2.2.txt rename to RelNotes/1.5.2.2.adoc diff --git a/RelNotes/1.5.2.3.txt b/RelNotes/1.5.2.3.adoc similarity index 100% rename from RelNotes/1.5.2.3.txt rename to RelNotes/1.5.2.3.adoc diff --git a/RelNotes/1.5.2.4.txt b/RelNotes/1.5.2.4.adoc similarity index 100% rename from RelNotes/1.5.2.4.txt rename to RelNotes/1.5.2.4.adoc diff --git a/RelNotes/1.5.2.5.txt b/RelNotes/1.5.2.5.adoc similarity index 100% rename from RelNotes/1.5.2.5.txt rename to RelNotes/1.5.2.5.adoc diff --git a/RelNotes/1.5.2.txt b/RelNotes/1.5.2.adoc similarity index 100% rename from RelNotes/1.5.2.txt rename to RelNotes/1.5.2.adoc diff --git a/RelNotes/1.5.3.1.txt b/RelNotes/1.5.3.1.adoc similarity index 100% rename from RelNotes/1.5.3.1.txt rename to RelNotes/1.5.3.1.adoc diff --git a/RelNotes/1.5.3.2.txt b/RelNotes/1.5.3.2.adoc similarity index 100% rename from RelNotes/1.5.3.2.txt rename to RelNotes/1.5.3.2.adoc diff --git a/RelNotes/1.5.3.3.txt b/RelNotes/1.5.3.3.adoc similarity index 100% rename from RelNotes/1.5.3.3.txt rename to RelNotes/1.5.3.3.adoc diff --git a/RelNotes/1.5.3.4.txt b/RelNotes/1.5.3.4.adoc similarity index 100% rename from RelNotes/1.5.3.4.txt rename to RelNotes/1.5.3.4.adoc diff --git a/RelNotes/1.5.3.5.txt b/RelNotes/1.5.3.5.adoc similarity index 100% rename from RelNotes/1.5.3.5.txt rename to RelNotes/1.5.3.5.adoc diff --git a/RelNotes/1.5.3.6.txt b/RelNotes/1.5.3.6.adoc similarity index 100% rename from RelNotes/1.5.3.6.txt rename to RelNotes/1.5.3.6.adoc diff --git a/RelNotes/1.5.3.7.txt b/RelNotes/1.5.3.7.adoc similarity index 100% rename from RelNotes/1.5.3.7.txt rename to RelNotes/1.5.3.7.adoc diff --git a/RelNotes/1.5.3.8.txt b/RelNotes/1.5.3.8.adoc similarity index 100% rename from RelNotes/1.5.3.8.txt rename to RelNotes/1.5.3.8.adoc diff --git a/RelNotes/1.5.3.txt b/RelNotes/1.5.3.adoc similarity index 100% rename from RelNotes/1.5.3.txt rename to RelNotes/1.5.3.adoc diff --git a/RelNotes/1.5.4.1.txt b/RelNotes/1.5.4.1.adoc similarity index 100% rename from RelNotes/1.5.4.1.txt rename to RelNotes/1.5.4.1.adoc diff --git a/RelNotes/1.5.4.2.txt b/RelNotes/1.5.4.2.adoc similarity index 100% rename from RelNotes/1.5.4.2.txt rename to RelNotes/1.5.4.2.adoc diff --git a/RelNotes/1.5.4.3.txt b/RelNotes/1.5.4.3.adoc similarity index 100% rename from RelNotes/1.5.4.3.txt rename to RelNotes/1.5.4.3.adoc diff --git a/RelNotes/1.5.4.4.txt b/RelNotes/1.5.4.4.adoc similarity index 100% rename from RelNotes/1.5.4.4.txt rename to RelNotes/1.5.4.4.adoc diff --git a/RelNotes/1.5.4.5.txt b/RelNotes/1.5.4.5.adoc similarity index 100% rename from RelNotes/1.5.4.5.txt rename to RelNotes/1.5.4.5.adoc diff --git a/RelNotes/1.5.4.6.txt b/RelNotes/1.5.4.6.adoc similarity index 100% rename from RelNotes/1.5.4.6.txt rename to RelNotes/1.5.4.6.adoc diff --git a/RelNotes/1.5.4.7.txt b/RelNotes/1.5.4.7.adoc similarity index 100% rename from RelNotes/1.5.4.7.txt rename to RelNotes/1.5.4.7.adoc diff --git a/RelNotes/1.5.4.txt b/RelNotes/1.5.4.adoc similarity index 100% rename from RelNotes/1.5.4.txt rename to RelNotes/1.5.4.adoc diff --git a/RelNotes/1.5.5.1.txt b/RelNotes/1.5.5.1.adoc similarity index 100% rename from RelNotes/1.5.5.1.txt rename to RelNotes/1.5.5.1.adoc diff --git a/RelNotes/1.5.5.2.txt b/RelNotes/1.5.5.2.adoc similarity index 100% rename from RelNotes/1.5.5.2.txt rename to RelNotes/1.5.5.2.adoc diff --git a/RelNotes/1.5.5.3.txt b/RelNotes/1.5.5.3.adoc similarity index 100% rename from RelNotes/1.5.5.3.txt rename to RelNotes/1.5.5.3.adoc diff --git a/RelNotes/1.5.5.4.txt b/RelNotes/1.5.5.4.adoc similarity index 100% rename from RelNotes/1.5.5.4.txt rename to RelNotes/1.5.5.4.adoc diff --git a/RelNotes/1.5.5.5.txt b/RelNotes/1.5.5.5.adoc similarity index 100% rename from RelNotes/1.5.5.5.txt rename to RelNotes/1.5.5.5.adoc diff --git a/RelNotes/1.5.5.6.txt b/RelNotes/1.5.5.6.adoc similarity index 100% rename from RelNotes/1.5.5.6.txt rename to RelNotes/1.5.5.6.adoc diff --git a/RelNotes/1.5.5.txt b/RelNotes/1.5.5.adoc similarity index 100% rename from RelNotes/1.5.5.txt rename to RelNotes/1.5.5.adoc diff --git a/RelNotes/1.5.6.1.txt b/RelNotes/1.5.6.1.adoc similarity index 100% rename from RelNotes/1.5.6.1.txt rename to RelNotes/1.5.6.1.adoc diff --git a/RelNotes/1.5.6.2.txt b/RelNotes/1.5.6.2.adoc similarity index 100% rename from RelNotes/1.5.6.2.txt rename to RelNotes/1.5.6.2.adoc diff --git a/RelNotes/1.5.6.3.txt b/RelNotes/1.5.6.3.adoc similarity index 100% rename from RelNotes/1.5.6.3.txt rename to RelNotes/1.5.6.3.adoc diff --git a/RelNotes/1.5.6.4.txt b/RelNotes/1.5.6.4.adoc similarity index 100% rename from RelNotes/1.5.6.4.txt rename to RelNotes/1.5.6.4.adoc diff --git a/RelNotes/1.5.6.5.txt b/RelNotes/1.5.6.5.adoc similarity index 100% rename from RelNotes/1.5.6.5.txt rename to RelNotes/1.5.6.5.adoc diff --git a/RelNotes/1.5.6.6.txt b/RelNotes/1.5.6.6.adoc similarity index 100% rename from RelNotes/1.5.6.6.txt rename to RelNotes/1.5.6.6.adoc diff --git a/RelNotes/1.5.6.txt b/RelNotes/1.5.6.adoc similarity index 100% rename from RelNotes/1.5.6.txt rename to RelNotes/1.5.6.adoc diff --git a/RelNotes/1.6.0.1.txt b/RelNotes/1.6.0.1.adoc similarity index 100% rename from RelNotes/1.6.0.1.txt rename to RelNotes/1.6.0.1.adoc diff --git a/RelNotes/1.6.0.2.txt b/RelNotes/1.6.0.2.adoc similarity index 100% rename from RelNotes/1.6.0.2.txt rename to RelNotes/1.6.0.2.adoc diff --git a/RelNotes/1.6.0.3.adoc b/RelNotes/1.6.0.3.adoc new file mode 100644 index 000000000..ad36c0f0b --- /dev/null +++ b/RelNotes/1.6.0.3.adoc @@ -0,0 +1,117 @@ +GIT v1.6.0.3 Release Notes +========================== + +Fixes since v1.6.0.2 +-------------------- + +* "git archive --format=zip" did not honor core.autocrlf while + --format=tar did. + +* Continuing "git rebase -i" was very confused when the user left modified + files in the working tree while resolving conflicts. + +* Continuing "git rebase -i" was also very confused when the user left + some staged changes in the index after "edit". + +* "git rebase -i" now honors the pre-rebase hook, just like the + other rebase implementations "git rebase" and "git rebase -m". + +* "git rebase -i" incorrectly aborted when there is no commit to replay. + +* Behaviour of "git diff --quiet" was inconsistent with "diff --exit-code" + with the output redirected to /dev/null. + +* "git diff --no-index" on binary files no longer outputs a bogus + "diff --git" header line. + +* "git diff" hunk header patterns with multiple elements separated by LF + were not used correctly. + +* Hunk headers in "git diff" default to using extended regular + expressions, fixing some of the internal patterns on non-GNU + platforms. + +* New config "diff.*.xfuncname" exposes extended regular expressions + for user specified hunk header patterns. + +* "git gc" when ejecting otherwise unreachable objects from packfiles into + loose form leaked memory. + +* "git index-pack" was recently broken and mishandled objects added by + thin-pack completion processing under memory pressure. + +* "git index-pack" was recently broken and misbehaved when run from inside + .git/objects/pack/ directory. + +* "git stash apply sash@{1}" was fixed to error out. Prior versions + would have applied stash@{0} incorrectly. + +* "git stash apply" now offers a better suggestion on how to continue + if the working tree is currently dirty. + +* "git for-each-ref --format=%(subject)" fixed for commits with no + newline in the message body. + +* "git remote" fixed to protect printf from user input. + +* "git remote show -v" now displays all URLs of a remote. + +* "git checkout -b branch" was confused when branch already existed. + +* "git checkout -q" once again suppresses the locally modified file list. + +* "git clone -q", "git fetch -q" asks remote side to not send + progress messages, actually making their output quiet. + +* Cross-directory renames are no longer used when creating packs. This + allows more graceful behavior on filesystems like sshfs. + +* Stale temporary files under $GIT_DIR/objects/pack are now cleaned up + automatically by "git prune". + +* "git merge" once again removes directories after the last file has + been removed from it during the merge. + +* "git merge" did not allocate enough memory for the structure itself when + enumerating the parents of the resulting commit. + +* "git blame -C -C" no longer segfaults while trying to pass blame if + it encounters a submodule reference. + +* "git rm" incorrectly claimed that you have local modifications when a + path was merely stat-dirty. + +* "git svn" fixed to display an error message when 'set-tree' failed, + instead of a Perl compile error. + +* "git submodule" fixed to handle checking out a different commit + than HEAD after initializing the submodule. + +* The "git commit" error message when there are still unmerged + files present was clarified to match "git write-tree". + +* "git init" was confused when core.bare or core.sharedRepository are set + in system or user global configuration file by mistake. When --bare or + --shared is given from the command line, these now override such + settings made outside the repositories. + +* Some segfaults due to uncaught NULL pointers were fixed in multiple + tools such as apply, reset, update-index. + +* Solaris builds now default to OLD_ICONV=1 to avoid compile warnings; + Solaris 8 does not define NEEDS_LIBICONV by default. + +* "Git.pm" tests relied on unnecessarily more recent version of Perl. + +* "gitweb" triggered undef warning on commits without log messages. + +* "gitweb" triggered undef warnings on missing trees. + +* "gitweb" now removes PATH_INFO from its URLs so users don't have + to manually set the URL in the gitweb configuration. + +* Bash completion removed support for legacy "git-fetch", "git-push" + and "git-pull" as these are no longer installed. Dashless form + ("git fetch") is still however supported. + +Many other documentation updates. diff --git a/RelNotes/1.6.0.3.txt b/RelNotes/1.6.0.3.txt deleted file mode 100644 index ae0577836..000000000 --- a/RelNotes/1.6.0.3.txt +++ /dev/null @@ -1,117 +0,0 @@ -GIT v1.6.0.3 Release Notes -========================== - -Fixes since v1.6.0.2 --------------------- - -* "git archive --format=zip" did not honor core.autocrlf while - --format=tar did. - -* Continuing "git rebase -i" was very confused when the user left modified - files in the working tree while resolving conflicts. - -* Continuing "git rebase -i" was also very confused when the user left - some staged changes in the index after "edit". - -* "git rebase -i" now honors the pre-rebase hook, just like the - other rebase implementations "git rebase" and "git rebase -m". - -* "git rebase -i" incorrectly aborted when there is no commit to replay. - -* Behaviour of "git diff --quiet" was inconsistent with "diff --exit-code" - with the output redirected to /dev/null. - -* "git diff --no-index" on binary files no longer outputs a bogus - "diff --git" header line. - -* "git diff" hunk header patterns with multiple elements separated by LF - were not used correctly. - -* Hunk headers in "git diff" default to using extended regular - expressions, fixing some of the internal patterns on non-GNU - platforms. - -* New config "diff.*.xfuncname" exposes extended regular expressions - for user specified hunk header patterns. - -* "git gc" when ejecting otherwise unreachable objects from packfiles into - loose form leaked memory. - -* "git index-pack" was recently broken and mishandled objects added by - thin-pack completion processing under memory pressure. - -* "git index-pack" was recently broken and misbehaved when run from inside - .git/objects/pack/ directory. - -* "git stash apply sash@{1}" was fixed to error out. Prior versions - would have applied stash@{0} incorrectly. - -* "git stash apply" now offers a better suggestion on how to continue - if the working tree is currently dirty. - -* "git for-each-ref --format=%(subject)" fixed for commits with no - no newline in the message body. - -* "git remote" fixed to protect printf from user input. - -* "git remote show -v" now displays all URLs of a remote. - -* "git checkout -b branch" was confused when branch already existed. - -* "git checkout -q" once again suppresses the locally modified file list. - -* "git clone -q", "git fetch -q" asks remote side to not send - progress messages, actually making their output quiet. - -* Cross-directory renames are no longer used when creating packs. This - allows more graceful behavior on filesystems like sshfs. - -* Stale temporary files under $GIT_DIR/objects/pack are now cleaned up - automatically by "git prune". - -* "git merge" once again removes directories after the last file has - been removed from it during the merge. - -* "git merge" did not allocate enough memory for the structure itself when - enumerating the parents of the resulting commit. - -* "git blame -C -C" no longer segfaults while trying to pass blame if - it encounters a submodule reference. - -* "git rm" incorrectly claimed that you have local modifications when a - path was merely stat-dirty. - -* "git svn" fixed to display an error message when 'set-tree' failed, - instead of a Perl compile error. - -* "git submodule" fixed to handle checking out a different commit - than HEAD after initializing the submodule. - -* The "git commit" error message when there are still unmerged - files present was clarified to match "git write-tree". - -* "git init" was confused when core.bare or core.sharedRepository are set - in system or user global configuration file by mistake. When --bare or - --shared is given from the command line, these now override such - settings made outside the repositories. - -* Some segfaults due to uncaught NULL pointers were fixed in multiple - tools such as apply, reset, update-index. - -* Solaris builds now default to OLD_ICONV=1 to avoid compile warnings; - Solaris 8 does not define NEEDS_LIBICONV by default. - -* "Git.pm" tests relied on unnecessarily more recent version of Perl. - -* "gitweb" triggered undef warning on commits without log messages. - -* "gitweb" triggered undef warnings on missing trees. - -* "gitweb" now removes PATH_INFO from its URLs so users don't have - to manually set the URL in the gitweb configuration. - -* Bash completion removed support for legacy "git-fetch", "git-push" - and "git-pull" as these are no longer installed. Dashless form - ("git fetch") is still however supported. - -Many other documentation updates. diff --git a/RelNotes/1.6.0.4.txt b/RelNotes/1.6.0.4.adoc similarity index 100% rename from RelNotes/1.6.0.4.txt rename to RelNotes/1.6.0.4.adoc diff --git a/RelNotes/1.6.0.5.txt b/RelNotes/1.6.0.5.adoc similarity index 100% rename from RelNotes/1.6.0.5.txt rename to RelNotes/1.6.0.5.adoc diff --git a/RelNotes/1.6.0.6.txt b/RelNotes/1.6.0.6.adoc similarity index 100% rename from RelNotes/1.6.0.6.txt rename to RelNotes/1.6.0.6.adoc diff --git a/RelNotes/1.6.0.txt b/RelNotes/1.6.0.adoc similarity index 100% rename from RelNotes/1.6.0.txt rename to RelNotes/1.6.0.adoc diff --git a/RelNotes/1.6.1.1.txt b/RelNotes/1.6.1.1.adoc similarity index 100% rename from RelNotes/1.6.1.1.txt rename to RelNotes/1.6.1.1.adoc diff --git a/RelNotes/1.6.1.2.txt b/RelNotes/1.6.1.2.adoc similarity index 100% rename from RelNotes/1.6.1.2.txt rename to RelNotes/1.6.1.2.adoc diff --git a/RelNotes/1.6.1.3.txt b/RelNotes/1.6.1.3.adoc similarity index 100% rename from RelNotes/1.6.1.3.txt rename to RelNotes/1.6.1.3.adoc diff --git a/RelNotes/1.6.1.4.txt b/RelNotes/1.6.1.4.adoc similarity index 100% rename from RelNotes/1.6.1.4.txt rename to RelNotes/1.6.1.4.adoc diff --git a/RelNotes/1.6.1.txt b/RelNotes/1.6.1.adoc similarity index 100% rename from RelNotes/1.6.1.txt rename to RelNotes/1.6.1.adoc diff --git a/RelNotes/1.6.2.1.txt b/RelNotes/1.6.2.1.adoc similarity index 100% rename from RelNotes/1.6.2.1.txt rename to RelNotes/1.6.2.1.adoc diff --git a/RelNotes/1.6.2.2.txt b/RelNotes/1.6.2.2.adoc similarity index 100% rename from RelNotes/1.6.2.2.txt rename to RelNotes/1.6.2.2.adoc diff --git a/RelNotes/1.6.2.3.txt b/RelNotes/1.6.2.3.adoc similarity index 100% rename from RelNotes/1.6.2.3.txt rename to RelNotes/1.6.2.3.adoc diff --git a/RelNotes/1.6.2.4.adoc b/RelNotes/1.6.2.4.adoc new file mode 100644 index 000000000..053dbb604 --- /dev/null +++ b/RelNotes/1.6.2.4.adoc @@ -0,0 +1,40 @@ +GIT v1.6.2.4 Release Notes +========================== + +Fixes since v1.6.2.3 +-------------------- + +* The configuration parser had a buffer overflow while parsing an overlong + value. + +* pruning reflog entries that are unreachable from the tip of the ref + during "git reflog prune" (hence "git gc") was very inefficient. + +* "git-add -p" lacked a way to say "q"uit to refuse staging any hunks for + the remaining paths. You had to say "d" and then ^C. + +* "git-checkout " did not update the index entry at + the named path; it now does. + +* "git-fast-export" choked when seeing a tag that does not point at commit. + +* "git init" segfaulted when given an overlong template location via + the --template= option. + +* "git-ls-tree" and "git-diff-tree" used a pathspec correctly when + deciding to descend into a subdirectory but they did not match the + individual paths correctly. This caused pathspecs "abc/d ab" to match + "abc/0" ("abc/d" made them decide to descend into the directory "abc/", + and then "ab" incorrectly matched "abc/0" when it shouldn't). + +* "git-merge-recursive" was broken when a submodule entry was involved in + a criss-cross merge situation. + +Many small documentation updates are included as well. + +--- +exec >/var/tmp/1 +echo O=$(git describe maint) +O=v1.6.2.3-38-g318b847 +git shortlog --no-merges $O..maint +--- diff --git a/RelNotes/1.6.2.4.txt b/RelNotes/1.6.2.4.txt deleted file mode 100644 index f4bf1d098..000000000 --- a/RelNotes/1.6.2.4.txt +++ /dev/null @@ -1,39 +0,0 @@ -GIT v1.6.2.4 Release Notes -========================== - -Fixes since v1.6.2.3 --------------------- - -* The configuration parser had a buffer overflow while parsing an overlong - value. - -* pruning reflog entries that are unreachable from the tip of the ref - during "git reflog prune" (hence "git gc") was very inefficient. - -* "git-add -p" lacked a way to say "q"uit to refuse staging any hunks for - the remaining paths. You had to say "d" and then ^C. - -* "git-checkout " did not update the index entry at - the named path; it now does. - -* "git-fast-export" choked when seeing a tag that does not point at commit. - -* "git init" segfaulted when given an overlong template location via - the --template= option. - -* "git-ls-tree" and "git-diff-tree" used a pathspec correctly when - deciding to descend into a subdirectory but they did not match the - individual paths correctly. This caused pathspecs "abc/d ab" to match - "abc/0" ("abc/d" made them decide to descend into the directory "abc/", - and then "ab" incorrectly matched "abc/0" when it shouldn't). - -* "git-merge-recursive" was broken when a submodule entry was involved in - a criss-cross merge situation. - -Many small documentation updates are included as well. - ---- -exec >/var/tmp/1 -echo O=$(git describe maint) -O=v1.6.2.3-38-g318b847 -git shortlog --no-merges $O..maint diff --git a/RelNotes/1.6.2.5.txt b/RelNotes/1.6.2.5.adoc similarity index 100% rename from RelNotes/1.6.2.5.txt rename to RelNotes/1.6.2.5.adoc diff --git a/RelNotes/1.6.2.adoc b/RelNotes/1.6.2.adoc new file mode 100644 index 000000000..166d73c60 --- /dev/null +++ b/RelNotes/1.6.2.adoc @@ -0,0 +1,164 @@ +GIT v1.6.2 Release Notes +======================== + +With the next major release, "git push" into a branch that is +currently checked out will be refused by default. You can choose +what should happen upon such a push by setting the configuration +variable receive.denyCurrentBranch in the receiving repository. + +To ease the transition plan, the receiving repository of such a +push running this release will issue a big warning when the +configuration variable is missing. Please refer to: + + https://archive.kernel.org/oldwiki/git.wiki.kernel.org/index.php/GitFaq.html#non-bare + https://lore.kernel.org/git/7vbptlsuyv.fsf@gitster.siamese.dyndns.org/ + +for more details on the reason why this change is needed and the +transition plan. + +For a similar reason, "git push $there :$killed" to delete the branch +$killed in a remote repository $there, if $killed branch is the current +branch pointed at by its HEAD, gets a large warning. You can choose what +should happen upon such a push by setting the configuration variable +receive.denyDeleteCurrent in the receiving repository. + + +Updates since v1.6.1 +-------------------- + +(subsystems) + +* git-svn updates. + +* gitweb updates, including a new patch view and RSS/Atom feed + improvements. + +* (contrib/emacs) git.el now has commands for checking out a branch, + creating a branch, cherry-picking and reverting commits; vc-git.el + is not shipped with git anymore (it is part of official Emacs). + +(performance) + +* pack-objects autodetects the number of CPUs available and uses threaded + version. + +(usability, bells and whistles) + +* automatic typo correction works on aliases as well + +* @{-1} is a way to refer to the last branch you were on. This is + accepted not only where an object name is expected, but anywhere + a branch name is expected and acts as if you typed the branch name. + E.g. "git branch --track mybranch @{-1}", "git merge @{-1}", and + "git rev-parse --symbolic-full-name @{-1}" would work as expected. + +* When refs/remotes/origin/HEAD points at a remote tracking branch that + has been pruned away, many git operations issued warning when they + internally enumerated the refs. We now warn only when you say "origin" + to refer to that pruned branch. + +* The location of .mailmap file can be configured, and its file format was + enhanced to allow mapping an incorrect e-mail field as well. + +* "git add -p" learned 'g'oto action to jump directly to a hunk. + +* "git add -p" learned to find a hunk with given text with '/'. + +* "git add -p" optionally can be told to work with just the command letter + without Enter. + +* when "git am" stops upon a patch that does not apply, it shows the + title of the offending patch. + +* "git am --directory=" and "git am --reject" passes these options + to underlying "git apply". + +* "git am" learned --ignore-date option. + +* "git blame" aligns author names better when they are spelled in + non US-ASCII encoding. + +* "git clone" now makes its best effort when cloning from an empty + repository to set up configuration variables to refer to the remote + repository. + +* "git checkout -" is a shorthand for "git checkout @{-1}". + +* "git cherry" defaults to whatever the current branch is tracking (if + exists) when the argument is not given. + +* "git cvsserver" can be told not to add extra "via git-CVS emulator" to + the commit log message it serves via gitcvs.commitmsgannotation + configuration. + +* "git cvsserver" learned to handle 'noop' command some CVS clients seem + to expect to work. + +* "git diff" learned a new option --inter-hunk-context to coalesce close + hunks together and show context between them. + +* The definition of what constitutes a word for "git diff --color-words" + can be customized via gitattributes, command line or a configuration. + +* "git diff" learned --patience to run "patience diff" algorithm. + +* "git filter-branch" learned --prune-empty option that discards commits + that do not change the contents. + +* "git fsck" now checks loose objects in alternate object stores, instead + of misreporting them as missing. + +* "git gc --prune" was resurrected to allow "git gc --no-prune" and + giving non-default expiration period e.g. "git gc --prune=now". + +* "git grep -w" and "git grep" for fixed strings have been optimized. + +* "git mergetool" learned -y(--no-prompt) option to disable prompting. + +* "git rebase -i" can transplant a history down to root to elsewhere + with --root option. + +* "git reset --merge" is a new mode that works similar to the way + "git checkout" switches branches, taking the local changes while + switching to another commit. + +* "git submodule update" learned --no-fetch option. + +* "git tag" learned --contains that works the same way as the same option + from "git branch". + + +Fixes since v1.6.1 +------------------ + +All of the fixes in v1.6.1.X maintenance series are included in this +release, unless otherwise noted. + +Here are fixes that this release has, but have not been backported to +v1.6.1.X series. + +* "git-add sub/file" when sub is a submodule incorrectly added the path to + the superproject. + +* "git bundle" did not exclude annotated tags even when a range given + from the command line wanted to. + +* "git filter-branch" unnecessarily refused to work when you had + checked out a different commit from what is recorded in the superproject + index in a submodule. + +* "git filter-branch" incorrectly tried to update a nonexistent work tree + at the end when it is run in a bare repository. + +* "git gc" did not work if your repository was created with an ancient git + and never had any pack files in it before. + +* "git mergetool" used to ignore autocrlf and other attributes + based content rewriting. + +* branch switching and merges had a silly bug that did not validate + the correct directory when making sure an existing subdirectory is + clean. + +* "git -p cmd" when cmd is not a built-in one left the display in funny state + when killed in the middle. diff --git a/RelNotes/1.6.2.txt b/RelNotes/1.6.2.txt deleted file mode 100644 index ad060f4f8..000000000 --- a/RelNotes/1.6.2.txt +++ /dev/null @@ -1,164 +0,0 @@ -GIT v1.6.2 Release Notes -======================== - -With the next major release, "git push" into a branch that is -currently checked out will be refused by default. You can choose -what should happen upon such a push by setting the configuration -variable receive.denyCurrentBranch in the receiving repository. - -To ease the transition plan, the receiving repository of such a -push running this release will issue a big warning when the -configuration variable is missing. Please refer to: - - http://git.or.cz/gitwiki/GitFaq#non-bare - http://thread.gmane.org/gmane.comp.version-control.git/107758/focus=108007 - -for more details on the reason why this change is needed and the -transition plan. - -For a similar reason, "git push $there :$killed" to delete the branch -$killed in a remote repository $there, if $killed branch is the current -branch pointed at by its HEAD, gets a large warning. You can choose what -should happen upon such a push by setting the configuration variable -receive.denyDeleteCurrent in the receiving repository. - - -Updates since v1.6.1 --------------------- - -(subsystems) - -* git-svn updates. - -* gitweb updates, including a new patch view and RSS/Atom feed - improvements. - -* (contrib/emacs) git.el now has commands for checking out a branch, - creating a branch, cherry-picking and reverting commits; vc-git.el - is not shipped with git anymore (it is part of official Emacs). - -(performance) - -* pack-objects autodetects the number of CPUs available and uses threaded - version. - -(usability, bells and whistles) - -* automatic typo correction works on aliases as well - -* @{-1} is a way to refer to the last branch you were on. This is - accepted not only where an object name is expected, but anywhere - a branch name is expected and acts as if you typed the branch name. - E.g. "git branch --track mybranch @{-1}", "git merge @{-1}", and - "git rev-parse --symbolic-full-name @{-1}" would work as expected. - -* When refs/remotes/origin/HEAD points at a remote tracking branch that - has been pruned away, many git operations issued warning when they - internally enumerated the refs. We now warn only when you say "origin" - to refer to that pruned branch. - -* The location of .mailmap file can be configured, and its file format was - enhanced to allow mapping an incorrect e-mail field as well. - -* "git add -p" learned 'g'oto action to jump directly to a hunk. - -* "git add -p" learned to find a hunk with given text with '/'. - -* "git add -p" optionally can be told to work with just the command letter - without Enter. - -* when "git am" stops upon a patch that does not apply, it shows the - title of the offending patch. - -* "git am --directory=" and "git am --reject" passes these options - to underlying "git apply". - -* "git am" learned --ignore-date option. - -* "git blame" aligns author names better when they are spelled in - non US-ASCII encoding. - -* "git clone" now makes its best effort when cloning from an empty - repository to set up configuration variables to refer to the remote - repository. - -* "git checkout -" is a shorthand for "git checkout @{-1}". - -* "git cherry" defaults to whatever the current branch is tracking (if - exists) when the argument is not given. - -* "git cvsserver" can be told not to add extra "via git-CVS emulator" to - the commit log message it serves via gitcvs.commitmsgannotation - configuration. - -* "git cvsserver" learned to handle 'noop' command some CVS clients seem - to expect to work. - -* "git diff" learned a new option --inter-hunk-context to coalesce close - hunks together and show context between them. - -* The definition of what constitutes a word for "git diff --color-words" - can be customized via gitattributes, command line or a configuration. - -* "git diff" learned --patience to run "patience diff" algorithm. - -* "git filter-branch" learned --prune-empty option that discards commits - that do not change the contents. - -* "git fsck" now checks loose objects in alternate object stores, instead - of misreporting them as missing. - -* "git gc --prune" was resurrected to allow "git gc --no-prune" and - giving non-default expiration period e.g. "git gc --prune=now". - -* "git grep -w" and "git grep" for fixed strings have been optimized. - -* "git mergetool" learned -y(--no-prompt) option to disable prompting. - -* "git rebase -i" can transplant a history down to root to elsewhere - with --root option. - -* "git reset --merge" is a new mode that works similar to the way - "git checkout" switches branches, taking the local changes while - switching to another commit. - -* "git submodule update" learned --no-fetch option. - -* "git tag" learned --contains that works the same way as the same option - from "git branch". - - -Fixes since v1.6.1 ------------------- - -All of the fixes in v1.6.1.X maintenance series are included in this -release, unless otherwise noted. - -Here are fixes that this release has, but have not been backported to -v1.6.1.X series. - -* "git-add sub/file" when sub is a submodule incorrectly added the path to - the superproject. - -* "git bundle" did not exclude annotated tags even when a range given - from the command line wanted to. - -* "git filter-branch" unnecessarily refused to work when you had - checked out a different commit from what is recorded in the superproject - index in a submodule. - -* "git filter-branch" incorrectly tried to update a nonexistent work tree - at the end when it is run in a bare repository. - -* "git gc" did not work if your repository was created with an ancient git - and never had any pack files in it before. - -* "git mergetool" used to ignore autocrlf and other attributes - based content rewriting. - -* branch switching and merges had a silly bug that did not validate - the correct directory when making sure an existing subdirectory is - clean. - -* "git -p cmd" when cmd is not a built-in one left the display in funny state - when killed in the middle. diff --git a/RelNotes/1.6.3.1.txt b/RelNotes/1.6.3.1.adoc similarity index 100% rename from RelNotes/1.6.3.1.txt rename to RelNotes/1.6.3.1.adoc diff --git a/RelNotes/1.6.3.2.txt b/RelNotes/1.6.3.2.adoc similarity index 100% rename from RelNotes/1.6.3.2.txt rename to RelNotes/1.6.3.2.adoc diff --git a/RelNotes/1.6.3.3.txt b/RelNotes/1.6.3.3.adoc similarity index 100% rename from RelNotes/1.6.3.3.txt rename to RelNotes/1.6.3.3.adoc diff --git a/RelNotes/1.6.3.4.txt b/RelNotes/1.6.3.4.adoc similarity index 100% rename from RelNotes/1.6.3.4.txt rename to RelNotes/1.6.3.4.adoc diff --git a/RelNotes/1.6.3.adoc b/RelNotes/1.6.3.adoc new file mode 100644 index 000000000..bbf177fc3 --- /dev/null +++ b/RelNotes/1.6.3.adoc @@ -0,0 +1,182 @@ +GIT v1.6.3 Release Notes +======================== + +With the next major release, "git push" into a branch that is +currently checked out will be refused by default. You can choose +what should happen upon such a push by setting the configuration +variable receive.denyCurrentBranch in the receiving repository. + +To ease the transition plan, the receiving repository of such a +push running this release will issue a big warning when the +configuration variable is missing. Please refer to: + + https://archive.kernel.org/oldwiki/git.wiki.kernel.org/index.php/GitFaq.html#non-bare + https://lore.kernel.org/git/7vbptlsuyv.fsf@gitster.siamese.dyndns.org/ + +for more details on the reason why this change is needed and the +transition plan. + +For a similar reason, "git push $there :$killed" to delete the branch +$killed in a remote repository $there, if $killed branch is the current +branch pointed at by its HEAD, gets a large warning. You can choose what +should happen upon such a push by setting the configuration variable +receive.denyDeleteCurrent in the receiving repository. + +When the user does not tell "git push" what to push, it has always +pushed matching refs. For some people it is unexpected, and a new +configuration variable push.default has been introduced to allow +changing a different default behaviour. To advertise the new feature, +a big warning is issued if this is not configured and a git push without +arguments is attempted. + + +Updates since v1.6.2 +-------------------- + +(subsystems) + +* various git-svn updates. + +* git-gui updates, including an update to Russian translation, and a + fix to an infinite loop when showing an empty diff. + +* gitk updates, including an update to Russian translation and improved Windows + support. + +(performance) + +* many uses of lstat(2) in the codepath for "git checkout" have been + optimized out. + +(usability, bells and whistles) + +* Boolean configuration variable yes/no can be written as on/off. + +* rsync:/path/to/repo can be used to run git over rsync for local + repositories. It may not be useful in practice; meant primarily for + testing. + +* http transport learned to prompt and use password when fetching from or + pushing to http://user@host.xz/ URL. + +* (msysgit) progress output that is sent over the sideband protocol can + be handled appropriately in Windows console. + +* "--pretty= + + + + +
+
+

Introduction

+
+
+

The Git development community is a widely distributed, diverse, ever-changing +group of individuals. Asynchronous communication via the Git mailing list poses +unique challenges when reviewing or discussing patches. This document contains +some guiding principles and helpful tools you can use to make your reviews both +more efficient for yourself and more effective for other contributors.

+
+
+

Note that none of the recommendations here are binding or in any way a +requirement of participation in the Git community. They are provided as a +resource to supplement your skills as a contributor.

+
+
+
+
+

Principles

+
+
+

Selecting patch(es) to review

+
+

If you are looking for a patch series in need of review, start by checking +the latest "What’s cooking in git.git" email +(example). The "What’s +cooking" emails & replies can be found using the query s:"What's cooking" on +the lore.kernel.org mailing list archive; +alternatively, you can find the contents of the "What’s cooking" email tracked +in whats-cooking.txt on the todo branch of Git. Topics tagged with "Needs +review" and those in the "[New Topics]" section are typically those that would +benefit the most from additional review.

+
+
+

Patches can also be searched manually in the mailing list archive using a query +like s:"PATCH" -s:"Re:". You can browse these results for topics relevant to +your expertise or interest.

+
+
+

If you’ve already contributed to Git, you may also be CC’d in another +contributor’s patch series. These are topics where the author feels that your +attention is warranted. This may be because their patch changes something you +wrote previously (making you a good judge of whether the new approach does or +doesn’t work), or because you have the expertise to provide an exceptionally +helpful review. There is no requirement to review these patches but, in the +spirit of open source collaboration, you should strongly consider doing so.

+
+
+
+

Reviewing patches

+
+

While every contributor takes their own approach to reviewing patches, here are +some general pieces of advice to make your reviews as clear and helpful as +possible. The advice is broken into two rough categories: high-level reviewing +guidance, and concrete tips for interacting with patches on the mailing list.

+
+
+

High-level guidance

+
+
    +
  • +

    Remember to review the content of commit messages for correctness and clarity, +in addition to the code change in the patch’s diff. The commit message of a +patch should accurately and fully explain the code change being made in the +diff.

    +
  • +
  • +

    Reviewing test coverage is an important - but easy to overlook - component of +reviews. A patch’s changes may be covered by existing tests, or new tests may +be introduced to exercise new behavior. Checking out a patch or series locally +allows you to manually mutate lines of new & existing tests to verify expected +pass/fail behavior. You can use this information to verify proper coverage or +to suggest additional tests the author could add.

    +
  • +
  • +

    When providing a recommendation, be as clear as possible about whether you +consider it "blocking" (the code would be broken or otherwise made worse if an +issue isn’t fixed) or "non-blocking" (the patch could be made better by taking +the recommendation, but acceptance of the series does not require it). +Non-blocking recommendations can be particularly ambiguous when they are +related to - but outside the scope of - a series ("nice-to-have"s), or when +they represent only stylistic differences between the author and reviewer.

    +
  • +
  • +

    When commenting on an issue, try to include suggestions for how the author +could fix it. This not only helps the author to understand and fix the issue, +it also deepens and improves your understanding of the topic.

    +
  • +
  • +

    Reviews do not need to exclusively point out problems. Positive +reviews indicate that it is not only the original author of the +patches who care about the issue the patches address, and are +highly encouraged.

    +
  • +
  • +

    Do not hesitate to give positive reviews on a series from your +work colleague. If your positive review is written well, it will +not make you look as if you two are representing corporate +interest on a series that is otherwise uninteresting to other +community members and shoving it down their throat.

    +
  • +
  • +

    Write a positive review in such a way that others can understand +why you support the goal, the approach, and the implementation the +patches took. Make sure to demonstrate that you did thoroughly read +the series and understood problem area well enough to be able to +say that the patches are written well. Feel free to "think out +loud" in your review: describe how you read & understood a complex section of +a patch, ask a question about something that confused you, point out something +you found exceptionally well-written, etc.

    +
  • +
  • +

    In particular, uplifting feedback goes a long way towards +encouraging contributors to participate more actively in the Git +community.

    +
  • +
+
+
+
+

Performing your review

+
+
    +
  • +

    Provide your review comments per-patch in a plaintext "Reply-All" email to the +relevant patch. Comments should be made inline, immediately below the relevant +section(s).

    +
  • +
  • +

    You may find that the limited context provided in the patch diff is sometimes +insufficient for a thorough review. In such cases, you can review patches in +your local tree by either applying patches with git-am(1) or checking +out the associated branch from https://github.com/gitster/git once the series +is tracked there.

    +
  • +
  • +

    Large, complicated patch diffs are sometimes unavoidable, such as when they +refactor existing code. If you find such a patch difficult to parse, try +reviewing the diff produced with the --color-moved and/or +--ignore-space-change options.

    +
  • +
  • +

    If a patch is long, you are encouraged to delete parts of it that are +unrelated to your review from the email reply. Make sure to leave enough +context for readers to understand your comments!

    +
  • +
  • +

    If you cannot complete a full review of a series all at once, consider letting +the author know (on- or off-list) if/when you plan to review the rest of the +series.

    +
  • +
+
+
+
+
+

Completing a review

+
+

Once each patch of a series is reviewed, the author (and/or other contributors) +may discuss the review(s). This may result in no changes being applied, or the +author will send a new version of their patch(es).

+
+
+

After a series is rerolled in response to your or others' review, make sure to +re-review the updates. If you are happy with the state of the patch series, +explicitly indicate your approval (typically with a reply to the latest +version’s cover letter). Optionally, you can let the author know that they can +add a "Reviewed-by: <you>" trailer if they resubmit the reviewed patch verbatim +in a later iteration of the series.

+
+
+

Finally, subsequent "What’s cooking" emails may explicitly ask whether a +reviewed topic is ready for merging to the next branch (typically phrased +"Will merge to 'next\'?"). You can help the maintainer and author by responding +with a short description of the state of your (and others', if applicable) +review, including the links to the relevant thread(s).

+
+
+
+
+
+

Terminology

+
+
+
+
nit:
+
+

Denotes a small issue that should be fixed, such as a typographical error +or misalignment of conditions in an if() statement.

+
+
aside:
+
optional:
+
non-blocking:
+
+

Indicates to the reader that the following comment should not block the +acceptance of the patch or series. These are typically recommendations +related to code organization & style, or musings about topics related to +the patch in question, but beyond its scope.

+
+
s/<before>/<after>/
+
+

Shorthand for "you wrote <before>, but I think you meant <after>," usually +for misspellings or other typographical errors. The syntax is a reference +to "substitute" command commonly found in Unix tools such as ed, sed, +vim, and perl.

+
+
cover letter
+
+

The "Patch 0" of a multi-patch series. This email describes the +high-level intent and structure of the patch series to readers on the +Git mailing list. It is also where the changelog notes and range-diff of +subsequent versions are provided by the author.

+
+

On single-patch submissions, cover letter content is typically not sent as a +separate email. Instead, it is inserted between the end of the patch’s commit +message (after the ---) and the beginning of the diff.

+
+
+
#leftoverbits
+
+

Used by either an author or a reviewer to describe features or suggested +changes that are out-of-scope of a given patch or series, but are relevant +to the topic for the sake of discussion.

+
+
+
+
+
+
+

See Also

+ +
+
+ + + \ No newline at end of file diff --git a/SubmittingPatches.adoc b/SubmittingPatches.adoc new file mode 100644 index 000000000..e270ccbe8 --- /dev/null +++ b/SubmittingPatches.adoc @@ -0,0 +1,886 @@ +Submitting Patches +================== + +== Guidelines + +Here are some guidelines for contributing back to this +project. There is also a link:MyFirstContribution.html[step-by-step tutorial] +available which covers many of these same guidelines. + +[[patch-flow]] +=== A typical life cycle of a patch series + +To help us understand the reason behind various guidelines given later +in the document, first let's understand how the life cycle of a +typical patch series for this project goes. + +. You come up with an itch. You code it up. You do not need any + pre-authorization from the project to do so. ++ +Your patches will be reviewed by other contributors on the mailing +list, and the reviews will be done to assess the merit of various +things, like the general idea behind your patch (including "is it +solving a problem worth solving in the first place?"), the reason +behind the design of the solution, and the actual implementation. +The guidelines given here are there to help your patches by making +them easier to understand by the reviewers. + +. You send the patches to the list and cc people who may need to know + about the change. Your goal is *not* necessarily to convince others + that what you are building is good. Your goal is to get help in + coming up with a solution for the "itch" that is better than what + you can build alone. ++ +The people who may need to know are the ones who worked on the code +you are touching. These people happen to be the ones who are +most likely to be knowledgeable enough to help you, but +they have no obligation to help you (i.e. you ask them for help, +you don't demand). +git log -p {litdd} _$area_you_are_modifying_+ would +help you find out who they are. + +. You get comments and suggestions for improvements. You may even get + them in an "on top of your change" patch form. You are expected to + respond to them with "Reply-All" on the mailing list, while taking + them into account while preparing an updated set of patches. + +. Polish, refine, and re-send your patches to the list and to the people + who spent their time to improve your patch. Go back to step (2). + +. While the above iterations improve your patches, the maintainer may + pick the patches up from the list and queue them to the `seen` + branch, in order to make it easier for people to play with it + without having to pick up and apply the patches to their trees + themselves. Being in `seen` has no other meaning. Specifically, it + does not mean the patch was "accepted" in any way. + +. When the discussion reaches a consensus that the latest iteration of + the patches are in good enough shape, the maintainer includes the + topic in the "What's cooking" report that are sent out a few times a + week to the mailing list, marked as "Will merge to 'next'." This + decision is primarily made by the maintainer with help from those + who participated in the review discussion. + +. After the patches are merged to the 'next' branch, the discussion + can still continue to further improve them by adding more patches on + top, but by the time a topic gets merged to 'next', it is expected + that everybody agrees that the scope and the basic direction of the + topic are appropriate, so such an incremental updates are limited to + small corrections and polishing. After a topic cooks for some time + (like 7 calendar days) in 'next' without needing further tweaks on + top, it gets merged to the 'master' branch and wait to become part + of the next major release. + +In the following sections, many techniques and conventions are listed +to help your patches get reviewed effectively in such a life cycle. + + +[[choose-starting-point]] +=== Choose a starting point. + +As a preliminary step, you must first choose a starting point for your +work. Typically this means choosing a branch, although technically +speaking it is actually a particular commit (typically the HEAD, or tip, +of the branch). + +There are several important branches to be aware of. Namely, there are +four integration branches as discussed in linkgit:gitworkflows[7]: + +* maint +* master +* next +* seen + +The branches lower on the list are typically descendants of the ones +that come before it. For example, `maint` is an "older" branch than +`master` because `master` usually has patches (commits) on top of +`maint`. + +There are also "topic" branches, which contain work from other +contributors. Topic branches are created by the Git maintainer (in +their fork) to organize the current set of incoming contributions on +the mailing list, and are itemized in the regular "What's cooking in +git.git" announcements. To find the tip of a topic branch, run `git log +--first-parent master..seen` and look for the merge commit. The second +parent of this commit is the tip of the topic branch. + +There is one guiding principle for choosing the right starting point: in +general, always base your work on the oldest integration branch that +your change is relevant to (see "Merge upwards" in +linkgit:gitworkflows[7]). What this principle means is that for the +vast majority of cases, the starting point for new work should be the +latest HEAD commit of `maint` or `master` based on the following cases: + +* If you are fixing bugs in the released version, use `maint` as the + starting point (which may mean you have to fix things without using + new API features on the cutting edge that recently appeared in + `master` but were not available in the released version). + +* Otherwise (such as if you are adding new features) use `master`. + + +NOTE: In exceptional cases, a bug that was introduced in an old +version may have to be fixed for users of releases that are much older +than the recent releases. `git describe --contains X` may describe +`X` as `v2.30.0-rc2-gXXXXXX` for the commit `X` that introduced the +bug, and the bug may be so high-impact that we may need to issue a new +maintenance release for Git 2.30.x series, when "Git 2.41.0" is the +current release. In such a case, you may want to use the tip of the +maintenance branch for the 2.30.x series, which may be available in the +`maint-2.30` branch in https://github.com/gitster/git[the maintainer's +"broken out" repo]. + +This also means that `next` or `seen` are inappropriate starting points +for your work, if you want your work to have a realistic chance of +graduating to `master`. They are simply not designed to be used as a +base for new work; they are only there to make sure that topics in +flight work well together. This is why both `next` and `seen` are +frequently re-integrated with incoming patches on the mailing list and +force-pushed to replace previous versions of themselves. A topic that is +literally built on top of `next` cannot be merged to `master` without +dragging in all the other topics in `next`, some of which may not be +ready. + +For example, if you are making tree-wide changes, while somebody else is +also making their own tree-wide changes, your work may have severe +overlap with the other person's work. This situation may tempt you to +use `next` as your starting point (because it would have the other +person's work included in it), but doing so would mean you'll not only +depend on the other person's work, but all the other random things from +other contributors that are already integrated into `next`. And as soon +as `next` is updated with a new version, all of your work will need to +be rebased anyway in order for them to be cleanly applied by the +maintainer. + +Under truly exceptional circumstances where you absolutely must depend +on a select few topic branches that are already in `next` but not in +`master`, you may want to create your own custom base-branch by forking +`master` and merging the required topic branches into it. You could then +work on top of this base-branch. But keep in mind that this base-branch +would only be known privately to you. So when you are ready to send +your patches to the list, be sure to communicate how you created it in +your cover letter. This critical piece of information would allow +others to recreate your base-branch on their end in order for them to +try out your work. + +Finally, note that some parts of the system have dedicated maintainers +with their own separate source code repositories (see the section +"Subsystems" below). + +[[separate-commits]] +=== 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. + +Give an explanation for the change(s) that is detailed enough so +that people can judge if it is good thing to do, without reading +the actual patch text to determine how well the code does what +the explanation promises to do. + +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. +That being said, patches which plainly describe the things that +help reviewers check the patch, and future maintainers understand +the code, are the most beautiful patches. Descriptions that summarize +the point in the subject well, and describe the motivation for the +change, the approach taken by the change, and if relevant how this +differs substantially from the prior version, are all good things +to have. + +Make sure that you have tests for the bug you are fixing. See +`t/README` for guidance. + +[[tests]] +When adding a new feature, make sure that you have new tests to show +the feature triggers the new behavior when it should, and to show the +feature does not trigger when it shouldn't. After any code change, +make sure that the entire test suite passes. When fixing a bug, make +sure you have new tests that break if somebody else breaks what you +fixed by accident to avoid regression. Also, try merging your work to +'next' and 'seen' and make sure the tests still pass; topics by others +that are still in flight may have unexpected interactions with what +you are trying to do in your topic. + +Pushing to a fork of https://github.com/git/git will use their CI +integration to test your changes on Linux, Mac and Windows. See the +<> section for details. + +Do not forget to update the documentation to describe the updated +behavior and make sure that the resulting documentation set formats +well (try the Documentation/doc-diff script). + +We currently have a liberal mixture of US and UK English norms for +spelling and grammar, which is somewhat unfortunate. A huge patch that +touches the files all over the place only to correct the inconsistency +is not welcome, though. Potential clashes with other changes that can +result from such a patch are not worth it. We prefer to gradually +reconcile the inconsistencies in favor of US English, with small and +easily digestible patches, as a side effect of doing some other real +work in the vicinity (e.g. rewriting a paragraph for clarity, while +turning en_UK spelling to en_US). Obvious typographical fixes are much +more welcomed ("teh -> "the"), preferably submitted as independent +patches separate from other documentation changes. + +[[whitespace-check]] +Oh, another thing. We are picky about whitespaces. Make sure your +changes do not trigger errors with the sample pre-commit hook shipped +in `templates/hooks--pre-commit`. To help ensure this does not happen, +run `git diff --check` on your changes before you commit. + +[[describe-changes]] +=== Describe your changes well. + +The log message that explains your changes is just as important as the +changes themselves. Your code may be clearly written with in-code +comment to sufficiently explain how it works with the surrounding +code, but those who need to fix or enhance your code in the future +will need to know _why_ your code does what it does, for a few +reasons: + +. Your code may be doing something differently from what you wanted it + to do. Writing down what you actually wanted to achieve will help + them fix your code and make it do what it should have been doing + (also, you often discover your own bugs yourself, while writing the + log message to summarize the thought behind it). + +. Your code may be doing things that were only necessary for your + immediate needs (e.g. "do X to directories" without implementing or + even designing what is to be done on files). Writing down why you + excluded what the code does not do will help guide future developers. + Writing down "we do X to directories, because directories have + characteristic Y" would help them infer "oh, files also have the same + characteristic Y, so perhaps doing X to them would also make sense?". + Saying "we don't do the same X to files, because ..." will help them + decide if the reasoning is sound (in which case they do not waste + time extending your code to cover files), or reason differently (in + which case, they can explain why they extend your code to cover + files, too). + +The goal of your log message is to convey the _why_ behind your change +to help future developers. The reviewers will also make sure that +your proposed log message will serve this purpose well. + +The first line of the commit message should be a short description (50 +characters is the soft limit, see DISCUSSION in linkgit:git-commit[1]), +and should skip the full stop. It is also conventional in most cases to +prefix the first line with "area: " where the area is a filename or +identifier for the general area of the code being modified, e.g. + +* doc: clarify distinction between sign-off and pgp-signing +* githooks.txt: improve the intro section + +If in doubt which identifier to use, run `git log --no-merges` on the +files you are modifying to see the current conventions. + +[[summary-section]] +The title sentence after the "area:" prefix omits the full stop at the +end, and its first word is not capitalized (the omission +of capitalization applies only to the word after the "area:" +prefix of the title) unless there is a reason to +capitalize it other than because it is the first word in the sentence. +E.g. "doc: clarify...", not "doc: Clarify...", or "githooks.txt: +improve...", not "githooks.txt: Improve...". But "refs: HEAD is also +treated as a ref" is correct, as we spell `HEAD` in all caps even when +it appears in the middle of a sentence. + +[[meaningful-message]] +The body should provide a meaningful commit message, which: + +. explains the problem the change tries to solve, i.e. what is wrong + with the current code without the change. + +. justifies the way the change solves the problem, i.e. why the + result with the change is better. + +. alternate solutions considered but discarded, if any. + +[[present-tense]] +The problem statement that describes the status quo is written in the +present tense. Write "The code does X when it is given input Y", +instead of "The code used to do Y when given input X". You do not +have to say "Currently"---the status quo in the problem statement is +about the code _without_ your change, by project convention. + +[[imperative-mood]] +Describe your changes in imperative mood, e.g. "make xyzzy do frotz" +instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy +to do frotz", as if you are giving orders to the codebase to change +its behavior. Try to make sure your explanation can be understood +without external resources. Instead of giving a URL to a mailing list +archive, summarize the relevant points of the discussion. + +[[commit-reference]] + +There are a few reasons why you may want to refer to another commit in +the "more stable" part of the history (i.e. on branches like `maint`, +`master`, and `next`): + +. A commit that introduced the root cause of a bug you are fixing. + +. A commit that introduced a feature that you are enhancing. + +. A commit that conflicts with your work when you made a trial merge + of your work into `next` and `seen` for testing. + +When you reference a commit on a more stable branch (like `master`, +`maint` and `next`), use the format "abbreviated hash (subject, +date)", like this: + +.... + Commit f86a374 (pack-bitmap.c: fix a memleak, 2015-03-30) + noticed that ... +.... + +The "Copy commit reference" command of gitk can be used to obtain this +format (with the subject enclosed in a pair of double-quotes), or this +invocation of `git show`: + +.... + git show -s --pretty=reference +.... + +or, on an older version of Git without support for --pretty=reference: + +.... + git show -s --date=short --pretty='format:%h (%s, %ad)' +.... + +[[sign-off]] +=== Certify your work by adding your `Signed-off-by` trailer + +To improve tracking of who did what, we ask you to certify that you +wrote the patch or have the right to pass it on under the same license +as ours, by "signing off" your patch. Without sign-off, we cannot +accept your patches. + +If (and only if) you certify the below D-C-O: + +[[dco]] +.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. +____ + +you add a "Signed-off-by" trailer to your commit, that looks like +this: + +.... + Signed-off-by: Random J Developer +.... + +This line can be added by Git if you run the git-commit command with +the -s option. + +Notice that you can place your own `Signed-off-by` trailer when +forwarding somebody else's patch with the above rules for +D-C-O. Indeed you are encouraged to do so. Do not forget to +place an in-body "From: " line at the beginning to properly attribute +the change to its true author (see (2) above). + +This procedure originally came from the Linux kernel project, so our +rule is quite similar to theirs, but what exactly it means to sign-off +your patch differs from project to project, so it may be different +from that of the project you are accustomed to. + +[[real-name]] +Please use a known identity in the `Signed-off-by` trailer, since we cannot +accept anonymous contributions. It is common, but not required, to use some form +of your real name. We realize that some contributors are not comfortable doing +so or prefer to contribute under a pseudonym or preferred name and we can accept +your patch either way, as long as the name and email you use are distinctive, +identifying, and not misleading. + +The goal of this policy is to allow us to have sufficient information to contact +you if questions arise about your contribution. + +[[commit-trailers]] +If you like, you can put extra trailers at the end: + +. `Reported-by:` is used to credit someone who found the bug that + the patch attempts to fix. +. `Acked-by:` says that the person who is more familiar with the area + the patch attempts to modify liked the patch. +. `Reviewed-by:`, unlike the other trailers, can only be offered by the + reviewers themselves when they are completely satisfied with the + patch after a detailed analysis. +. `Tested-by:` is used to indicate that the person applied the patch + and found it to have the desired effect. +. `Co-authored-by:` is used to indicate that people exchanged drafts + of a patch before submitting it. +. `Helped-by:` is used to credit someone who suggested ideas for + changes without providing the precise changes in patch form. +. `Mentored-by:` is used to credit someone with helping develop a + patch as part of a mentorship program (e.g., GSoC or Outreachy). +. `Suggested-by:` is used to credit someone with suggesting the idea + for a patch. + +While you can also create your own trailer if the situation warrants it, we +encourage you to instead use one of the common trailers in this project +highlighted above. + +Only capitalize the very first letter of the trailer, i.e. favor +"Signed-off-by" over "Signed-Off-By" and "Acked-by:" over "Acked-By". + +[[ai]] +=== Use of Artificial Intelligence (AI) + +The Developer's Certificate of Origin requires contributors to certify +that they know the origin of their contributions to the project and +that they have the right to submit it under the project's license. +It's not yet clear that this can be legally satisfied when submitting +significant amount of content that has been generated by AI tools. + +Another issue with AI generated content is that AIs still often +hallucinate or just produce bad code, commit messages, documentation +or output, even when you point out their mistakes. + +To avoid these issues, we will reject anything that looks AI +generated, that sounds overly formal or bloated, that looks like AI +slop, that looks good on the surface but makes no sense, or that +senders don’t understand or cannot explain. + +We strongly recommend using AI tools carefully and responsibly. + +Contributors would often benefit more from AI by using it to guide and +help them step by step towards producing a solution by themselves +rather than by asking for a full solution that they would then mostly +copy-paste. They can also use AI to help with debugging, or with +checking for obvious mistakes, things that can be improved, things +that don’t match our style, guidelines or our feedback, before sending +it to us. + +[[git-tools]] +=== Generate your patch using Git tools out of your commits. + +Git based diff tools 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. + +[[review-patch]] +Please make sure your patch does not add commented out debugging code, +or include any extra files which do not relate to what your patch +is trying to achieve. Make sure to review +your patch after generating it, to ensure accuracy. Before +sending out, please make sure it cleanly applies to the starting point you +have chosen in the "Choose a starting point" section. + +NOTE: From the perspective of those reviewing your patch, the `master` +branch is the default expected starting point. So if you have chosen a +different starting point, please communicate this choice in your cover +letter. + + +[[send-patches]] +=== Sending your patches. + +==== Choosing your reviewers + +:security-ml: footnoteref:[security-ml,The Git Security mailing list: git-security@googlegroups.com] + +NOTE: Patches that may be +security relevant should be submitted privately to the Git Security +mailing list{security-ml}, instead of the public mailing list. + +:contrib-scripts: footnoteref:[contrib-scripts,Scripts under `contrib/` are + +not part of the core `git` binary and must be called directly. Clone the Git + +codebase and run `perl contrib/contacts/git-contacts`.] + +Send your patch with "To:" set to the mailing list, with "cc:" listing +people who are involved in the area you are touching (the `git-contacts` +script in `contrib/contacts/`{contrib-scripts} can help to +identify them), to solicit comments and reviews. Also, when you made +trial merges of your topic to `next` and `seen`, you may have noticed +work by others conflicting with your changes. There is a good possibility +that these people may know the area you are touching well. + +If you are using `send-email`, you can feed it the output of `git-contacts` like +this: + +.... + git send-email --cc-cmd='perl contrib/contacts/git-contacts' feature/*.patch +.... + +:current-maintainer: footnote:[The current maintainer: gitster@pobox.com] +:git-ml: footnote:[The mailing list: git@vger.kernel.org] + +After the list reached a consensus that it is a good idea to apply the +patch, re-send it with "To:" set to the maintainer{current-maintainer} +and "cc:" the list{git-ml} for inclusion. This is especially relevant +when the maintainer did not heavily participate in the discussion and +instead left the review to trusted others. + +Do not forget to add trailers such as `Acked-by:`, `Reviewed-by:` and +`Tested-by:` lines as necessary to credit people who helped your +patch, and "cc:" them when sending such a final version for inclusion. + +==== `format-patch` and `send-email` + +Learn to use `format-patch` and `send-email` if possible. These commands +are optimized for the workflow of sending patches, avoiding many ways +your existing e-mail client (often optimized for "multipart/*" MIME +type e-mails) might render your patches unusable. + +NOTE: Here we outline the procedure using `format-patch` and +`send-email`, but you can instead use GitGitGadget to send in your +patches (see link:MyFirstContribution.html[MyFirstContribution]). + +People on the Git mailing list need to be able to read and +comment on the changes you are submitting. It is important for +a developer to be able to "quote" your changes, using standard +e-mail tools, so that they may comment on specific portions of +your code. For this reason, each patch should be submitted +"inline" in a separate message. + +All subsequent versions of a patch series and other related patches should be +grouped into their own e-mail thread to help readers find all parts of the +series. To that end, send them as replies to either an additional "cover +letter" message (see below), the first patch, or the respective preceding patch. +Here is a link:MyFirstContribution.html#v2-git-send-email[step-by-step guide] on +how to submit updated versions of a patch series. + +If your log message (including your name on the +`Signed-off-by` trailer) is not writable in ASCII, make sure that +you send off a message in the correct encoding. + +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. Use of markers in addition to PATCH within +the brackets to describe the nature of the patch is also +encouraged. E.g. [RFC PATCH] (where RFC stands for "request for +comments") is often used to indicate a patch needs further +discussion before being accepted, [PATCH v2], [PATCH v3] etc. +are often seen when you are sending an update to what you have +previously sent. + +The `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` trailers, 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. +To change the default "[PATCH]" in the subject to "[]", use +`git format-patch --subject-prefix=`. As a shortcut, you +can use `--rfc` instead of `--subject-prefix="RFC PATCH"`, or +`-v ` instead of `--subject-prefix="PATCH v"`. + +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 line and the diffstat. For +patches requiring multiple iterations of review and discussion, +an explanation of changes between each iteration can be kept in +Git-notes and inserted automatically following the three-dash +line via `git format-patch --notes`. + +[[the-topic-summary]] +*This is EXPERIMENTAL*. + +When sending a topic, you can optionally propose a topic name and/or a +one-paragraph summary that should appear in the "What's cooking" +report when it is picked up to explain the topic. If you choose to do +so, please write a 2-5 line paragraph that will fit well in our +release notes (see many bulleted entries in the +Documentation/RelNotes/* files for examples), and make it the first +(or second, if including a suggested topic name) paragraph of the +cover letter. If suggesting a topic name, use the format +"XX/your-topic-name", where "XX" is a stand-in for the primary +author's initials, and "your-topic-name" is a brief, dash-delimited +description of what your topic does. For a single-patch series, use +the space between the three-dash line and the diffstat, as described +earlier. + +[[multi-series-efforts]] +If your patch series is part of a larger effort spanning multiple +patch series, briefly describe the broader goal, and state where the +current series fits into that goal. If you are suggesting a topic +name as in <>, consider +"XX/the-broader-goal-part-one", "XX/the-broader-goal-part-two", and so +on. + +[[attachment]] +Do not attach the patch as a MIME attachment, compressed or not. +Do not let your e-mail client send quoted-printable. Do not let +your e-mail client send format=flowed which would destroy +whitespaces in your patches. 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. + +[[pgp-signature]] +Do not PGP sign your patch. 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. + +=== Handling Conflicts and Iterating Patches + +When revising changes made to your patches, it's important to +acknowledge the possibility of conflicts with other ongoing topics. To +navigate these potential conflicts effectively, follow the recommended +steps outlined below: + +. Build on a suitable base branch, see the <>, +and format-patch the series. If you are doing "rebase -i" in-place to +update from the previous round, this will reuse the previous base so +(2) and (3) may become trivial. + +. Find the base of where the last round was queued ++ + $ mine='kn/ref-transaction-symref' + $ git checkout "origin/seen^{/^Merge branch '$mine'}...master" + +. Apply your format-patch result. There are two cases +.. Things apply cleanly and tests fine. Go to (4). +.. Things apply cleanly but does not build or test fails, or things do +not apply cleanly. ++ +In the latter case, you have textual or semantic conflicts coming from +the difference between the old base and the base you used to build in +(1). Identify what caused the breakages (e.g., a topic or two may have +merged since the base used by (2) until the base used by (1)). ++ +Check out the latest 'origin/master' (which may be newer than the base +used by (2)), "merge --no-ff" the topics you newly depend on in there, +and use the result of the merge(s) as the base, rebuild the series and +test again. Run format-patch from the last such merges to the tip of +your topic. If you did ++ + $ git checkout origin/master + $ git merge --no-ff --into-name kn/ref-transaction-symref fo/obar + $ git merge --no-ff --into-name kn/ref-transaction-symref ba/zqux + ... rebuild the topic ... ++ +Then you'd just format your topic above these "preparing the ground" +merges, e.g. ++ + $ git format-patch "HEAD^{/^Merge branch 'ba/zqux'}"..HEAD ++ +Do not forget to write in the cover letter you did this, including the +topics you have in your base on top of 'master'. Then go to (4). + +. Make a trial merge of your topic into 'next' and 'seen', e.g. ++ + $ git checkout --detach 'origin/seen' + $ git revert -m 1 + $ git merge kn/ref-transaction-symref ++ +The "revert" is needed if the previous iteration of your topic is +already in 'seen' (like in this case). You could choose to rebuild +master..origin/seen from scratch while excluding your previous +iteration, which may emulate what happens on the maintainers end more +closely. ++ +This trial merge may conflict. It is primarily to see what conflicts +_other_ topics may have with your topic. In other words, you do not +have to depend on it to make your topic work on 'master'. It may +become the job of the other topic owners to resolve conflicts if your +topic goes to 'next' before theirs. ++ +Make a note on what conflict you saw in the cover letter. You do not +necessarily have to resolve them, but it would be a good opportunity to +learn what others are doing in related areas. ++ + $ git checkout --detach 'origin/next' + $ git merge kn/ref-transaction-symref ++ +This is to see what conflicts your topic has with other topics that are +already cooking. This should not conflict if (3)-2 prepared a base on +top of updated master plus dependent topics taken from 'next'. Unless +the context is severe (one way to tell is try the same trial merge with +your old iteration, which may conflict in a similar way), expect that it +will be handled on maintainers end (if it gets unmanageable, I'll ask to +rebase when I receive your patches). + +== Subsystems with dedicated maintainers + +Some parts of the system have dedicated maintainers with their own +repositories. + +- `git-gui/` comes from the git-gui project, maintained by Johannes Sixt: + + https://github.com/j6t/git-gui + + Contibutions should go via the git mailing list. + +- `gitk-git/` comes from the gitk project, maintained by Johannes Sixt: + + https://github.com/j6t/gitk + + Contibutions should go via the git mailing list. + +- `po/` comes from the localization coordinator, Jiang Xin: + + https://github.com/git-l10n/git-po/ + +Patches to these parts should be based on their trees. + +- The "Git documentation translations" project, led by Jean-Noël + Avila, translates our documentation pages. Their work products are + maintained separately from this project, not as part of our tree: + + https://github.com/jnavila/git-manpages-l10n/ + + +== GitHub CI[[GHCI]] + +With an account at GitHub, you can use GitHub CI to test your changes +on Linux, Mac and Windows. See +https://github.com/git/git/actions/workflows/main.yml for examples of +recent CI runs. + +Follow these steps for the initial setup: + +. Fork https://github.com/git/git to your GitHub account. + You can find detailed instructions how to fork here: + https://help.github.com/articles/fork-a-repo/ + +After the initial setup, CI will run whenever you push new changes +to your fork of Git on GitHub. You can monitor the test state of all your +branches here: `https://github.com//git/actions/workflows/main.yml` + +If a branch does not pass all test cases then it will be marked with a +red +x+, instead of a green check. In that case, you can click on the +failing job and navigate to "ci/run-build-and-tests.sh" and/or +"ci/print-test-failures.sh". You can also download "Artifacts" which +are zip archives containing tarred (or zipped) archives with test data +relevant for debugging. + +Then fix the problem and push your fix to your GitHub fork. This will +trigger a new CI build to ensure all tests pass. + +[[mua]] +== MUA specific hints + +Some of the 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. + +See the DISCUSSION section of linkgit:git-format-patch[1] for hints on +checking your patch by mailing it to yourself and applying with +linkgit:git-am[1]. + +While you are at it, check the resulting commit log message from +a trial run of applying the patch. If what is in the resulting +commit is not exactly what you would want to see, 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, KMail, GMail + +See the MUA-SPECIFIC HINTS section of linkgit:git-format-patch[1]. + +=== Gnus + +"|" in the `*Summary*` buffer can be used to pipe the current +message to an external program, and this is a handy way to drive +`git am`. However, if the message is MIME encoded, what is +piped into the program is the representation you see in your +`*Article*` buffer after unwrapping MIME. This is often not what +you would want for two reasons. It tends to screw up non-ASCII +characters (most notably in people's names), and also +whitespaces (fatal in patches). Running "C-u g" to display the +message in raw form before using "|" to run the pipe can work +this problem around. diff --git a/SubmittingPatches.html b/SubmittingPatches.html index 68d059762..bebb8428f 100644 --- a/SubmittingPatches.html +++ b/SubmittingPatches.html @@ -1,1390 +1,1645 @@ - - - - - - -Submitting Patches - - - - - -
-
-

Guidelines

-
-

Here are some guidelines for people who want to contribute their code -to this software.

-
-

Decide what to base your work on.

-

In general, always base your work on the oldest branch that your -change is relevant to.

-
    -
  • -

    -A bugfix should be based on maint in general. If the bug is not - present in maint, base it on master. For a bug that’s not yet - in master, find the topic that introduces the regression, and - base your work on the tip of the topic. -

    -
  • -
  • -

    -A new feature should be based on master in general. If the new - feature depends on a topic that is in pu, but not in master, - base your work on the tip of that topic. -

    -
  • -
  • -

    -Corrections and enhancements to a topic not yet in master should - be based on the tip of that topic. If the topic has not been merged - to next, it’s alright to add a note to squash minor corrections - into the series. -

    -
  • -
  • -

    -In the exceptional case that a new feature depends on several topics - not in master, start working on next or pu privately and send - out patches for discussion. Before the final merge, you may have to - wait until some of the dependent topics graduate to master, and - rebase your work. -

    -
  • -
  • -

    -Some parts of the system have dedicated maintainers with their own - repositories (see the section "Subsystems" below). Changes to - these parts should be based on their trees. -

    -
  • -
-

To find the tip of a topic branch, run git log --first-parent -master..pu and look for the merge commit. The second parent of this -commit is the tip of the topic branch.

-
-
-

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.

-

Give an explanation for the change(s) that is detailed enough so -that people can judge if it is good thing to do, without reading -the actual patch text to determine how well the code does what -the explanation promises to do.

-

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. -That being said, patches which plainly describe the things that -help reviewers check the patch, and future maintainers understand -the code, are the most beautiful patches. Descriptions that summarize -the point in the subject well, and describe the motivation for the -change, the approach taken by the change, and if relevant how this -differs substantially from the prior version, are all good things -to have.

-

Make sure that you have tests for the bug you are fixing. See -t/README for guidance.

-

When adding a new feature, make sure that you have new tests to show -the feature triggers the new behavior when it should, and to show the -feature does not trigger when it shouldn’t. After any code change, make -sure that the entire test suite passes.

-

If you have an account at GitHub (and you can get one for free to work -on open source projects), you can use their Travis CI integration to -test your changes on Linux, Mac (and hopefully soon Windows). See -GitHub-Travis CI hints section for details.

-

Do not forget to update the documentation to describe the updated -behavior and make sure that the resulting documentation set formats -well (try the Documentation/doc-diff script).

-

We currently have a liberal mixture of US and UK English norms for -spelling and grammar, which is somewhat unfortunate. A huge patch that -touches the files all over the place only to correct the inconsistency -is not welcome, though. Potential clashes with other changes that can -result from such a patch are not worth it. We prefer to gradually -reconcile the inconsistencies in favor of US English, with small and -easily digestible patches, as a side effect of doing some other real -work in the vicinity (e.g. rewriting a paragraph for clarity, while -turning en_UK spelling to en_US). Obvious typographical fixes are much -more welcomed ("teh → "the"), preferably submitted as independent -patches separate from other documentation changes.

-

Oh, another thing. We are picky about whitespaces. Make sure your -changes do not trigger errors with the sample pre-commit hook shipped -in templates/hooks--pre-commit. To help ensure this does not happen, -run git diff --check on your changes before you commit.

-
-
-

Describe your changes well.

-

The first line of the commit message should be a short description (50 -characters is the soft limit, see DISCUSSION in git-commit(1)), -and should skip the full stop. It is also conventional in most cases to -prefix the first line with "area: " where the area is a filename or -identifier for the general area of the code being modified, e.g.

-
    -
  • -

    -doc: clarify distinction between sign-off and pgp-signing -

    -
  • -
  • -

    -githooks.txt: improve the intro section -

    -
  • -
-

If in doubt which identifier to use, run git log --no-merges on the -files you are modifying to see the current conventions.

-

It’s customary to start the remainder of the first line after "area: " -with a lower-case letter. E.g. "doc: clarify…", not "doc: -Clarify…", or "githooks.txt: improve…", not "githooks.txt: -Improve…".

-

The body should provide a meaningful commit message, which:

-
    -
  1. -

    -explains the problem the change tries to solve, i.e. what is wrong - with the current code without the change. -

    -
  2. -
  3. -

    -justifies the way the change solves the problem, i.e. why the - result with the change is better. -

    -
  4. -
  5. -

    -alternate solutions considered but discarded, if any. -

    -
  6. -
-

Describe your changes in imperative mood, e.g. "make xyzzy do frotz" -instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy -to do frotz", as if you are giving orders to the codebase to change -its behavior. Try to make sure your explanation can be understood -without external resources. Instead of giving a URL to a mailing list -archive, summarize the relevant points of the discussion.

-

If you want to reference a previous commit in the history of a stable -branch, use the format "abbreviated sha1 (subject, date)", -with the subject enclosed in a pair of double-quotes, like this:

-
-
-
        Commit f86a374 ("pack-bitmap.c: fix a memleak", 2015-03-30)
-        noticed that ...
-
-

The "Copy commit summary" command of gitk can be used to obtain this -format, or this invocation of git show:

-
-
-
        git show -s --date=short --pretty='format:%h ("%s", %ad)' <commit>
-
-
-
-

Generate your patch using Git tools out of your commits.

-

Git based diff tools 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 add commented out debugging code, -or include any extra files which do not relate to what your patch -is trying to achieve. 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.

-
-
-

Sending your patches.

-

Before sending any patches, please note that patches that may be -security relevant should be submitted privately to the Git Security -mailing list
[The Git Security mailing list: git-security@googlegroups.com]
, instead of the public mailing list.

-

Learn to use format-patch and send-email if possible. These commands -are optimized for the workflow of sending patches, avoiding many ways -your existing e-mail client that is optimized for "multipart/*" mime -type e-mails to corrupt and render your patches unusable.

-

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, each patch should be submitted -"inline" in a separate message.

-

Multiple related patches should be grouped into their own e-mail -thread to help readers find all parts of the series. To that end, -send them as replies to either an additional "cover letter" message -(see below), the first patch, or the respective preceding patch.

-

If your log message (including your name on the -Signed-off-by line) is not writable in ASCII, make sure that -you send off a message in the correct encoding.

-
- - - -
-
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. Use of markers in addition to PATCH within -the brackets to describe the nature of the patch is also -encouraged. E.g. [RFC PATCH] (where RFC stands for "request for -comments") is often used to indicate a patch needs further -discussion before being accepted, [PATCH v2], [PATCH v3] etc. -are often seen when you are sending an update to what you have -previously sent.

-

The 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. -To change the default "[PATCH]" in the subject to "[<text>]", use -git format-patch --subject-prefix=<text>. As a shortcut, you -can use --rfc instead of --subject-prefix="RFC PATCH", or --v <n> instead of --subject-prefix="PATCH v<n>".

-

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 line and the diffstat. For -patches requiring multiple iterations of review and discussion, -an explanation of changes between each iteration can be kept in -Git-notes and inserted automatically following the three-dash -line via git format-patch --notes.

-

Do not attach the patch as a MIME attachment, compressed or not. -Do not let your e-mail client send quoted-printable. Do not let -your e-mail client send format=flowed which would destroy -whitespaces in your patches. 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. 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.

-

As mentioned at the beginning of the section, patches that may be -security relevant should not be submitted to the public mailing list -mentioned below, but should instead be sent privately to the Git -Security mailing list
[security-ml]
.

-

Send your patch with "To:" set to the mailing list, with "cc:" listing -people who are involved in the area you are touching (the git -contacts command in contrib/contacts/ can help to -identify them), to solicit comments and reviews.

-

After the list reached a consensus that it is a good idea to apply the -patch, re-send it with "To:" set to the maintainer
[The current maintainer: gitster@pobox.com]
and "cc:" the -list
[The mailing list: git@vger.kernel.org]
for inclusion.

-

Do not forget to add trailers such as Acked-by:, Reviewed-by: and -Tested-by: lines as necessary to credit people who helped your -patch.

-
-
-

Certify your work by adding your "Signed-off-by: " line

-

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 an open-source patch. The rules are -pretty simple: if you can certify the below D-C-O:

-
-
Developer’s Certificate of Origin 1.1
-
-

By making a contribution to this project, I certify that:

-
    -
  1. -

    -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 -

    -
  2. -
  3. -

    -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 -

    -
  4. -
  5. -

    -The contribution was provided directly to me by some other - person who certified (a), (b) or (c) and I have not modified - it. -

    -
  6. -
  7. -

    -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. -

    -
  8. -
-
-
-
-

then you just add a line saying

-
-
-
        Signed-off-by: Random J Developer <random@developer.example.org>
-
-

This line can be automatically added by Git if you run the git-commit -command with the -s option.

-

Notice that you can place your own Signed-off-by: line when -forwarding somebody else’s patch with the above rules for -D-C-O. Indeed you are encouraged to do so. Do not forget to -place an in-body "From: " line at the beginning to properly attribute -the change to its true author (see (2) above).

-

Also notice that a real name is used in the Signed-off-by: line. Please -don’t hide your real name.

-

If you like, you can put extra tags at the end:

-
    -
  1. -

    -Reported-by: is used to credit someone who found the bug that - the patch attempts to fix. -

    -
  2. -
  3. -

    -Acked-by: says that the person who is more familiar with the area - the patch attempts to modify liked the patch. -

    -
  4. -
  5. -

    -Reviewed-by:, unlike the other tags, can only be offered by the - reviewer and means that she is completely satisfied that the patch - is ready for application. It is usually offered only after a - detailed review. -

    -
  6. -
  7. -

    -Tested-by: is used to indicate that the person applied the patch - and found it to have the desired effect. -

    -
  8. -
-

You can also create your own tag or use one that’s in common usage -such as "Thanks-to:", "Based-on-patch-by:", or "Mentored-by:".

-
-
-
-
-

Subsystems with dedicated maintainers

-
-

Some parts of the system have dedicated maintainers with their own -repositories.

-
    -
  • -

    -git-gui/ comes from git-gui project, maintained by Pat Thoyts: -

    -
    -
    -
    git://repo.or.cz/git-gui.git
    -
    -
  • -
  • -

    -gitk-git/ comes from Paul Mackerras’s gitk project: -

    -
    -
    -
    git://ozlabs.org/~paulus/gitk
    -
    -
  • -
  • -

    -po/ comes from the localization coordinator, Jiang Xin: -

    -
    -
    -
    https://github.com/git-l10n/git-po/
    -
    -
  • -
-

Patches to these parts should be based on their trees.

-
-
-
-

An ideal patch flow

-
-

Here is an ideal patch flow for this project the current maintainer -suggests to the contributors:

-
    -
  1. -

    -You come up with an itch. You code it up. -

    -
  2. -
  3. -

    -Send it to the list and cc people who may need to know about - the change. -

    -

    The people who may need to know are the ones whose code you -are butchering. These people happen to be the ones who are -most likely to be knowledgeable enough to help you, but -they have no obligation to help you (i.e. you ask for help, -don’t demand). git log -p -- $area_you_are_modifying would -help you find out who they are.

    -
  4. -
  5. -

    -You get comments and suggestions for improvements. You may - even get them in an "on top of your change" patch form. -

    -
  6. -
  7. -

    -Polish, refine, and re-send to the list and the people who - spend their time to improve your patch. Go back to step (2). -

    -
  8. -
  9. -

    -The list forms consensus that the last round of your patch is - good. Send it to the maintainer and cc the list. -

    -
  10. -
  11. -

    -A topic branch is created with the patch and is merged to next, - and cooked further and eventually graduates to master. -

    -
  12. -
-

In any time between the (2)-(3) cycle, the maintainer may pick it up -from the list and queue it to pu, in order to make it easier for -people play with it without having to pick up and apply the patch to -their trees themselves.

-
-
-
-

Know the status of your patch after submission

-
-
    -
  • -

    -You can use Git itself to find out when your patch is merged in - master. git pull --rebase will automatically skip already-applied - patches, and will let you know. This works only if you rebase on top - of the branch in which your patch has been merged (i.e. it will not - tell you if your patch is merged in pu if you rebase on top of - master). -

    -
  • -
  • -

    -Read the Git mailing list, the maintainer regularly posts messages - entitled "What’s cooking in git.git" and "What’s in git.git" giving - the status of various proposed changes. -

    -
  • -
-
-
-
-

GitHub-Travis CI hints

-
-

With an account at GitHub (you can get one for free to work on open -source projects), you can use Travis CI to test your changes on Linux, -Mac (and hopefully soon Windows). You can find a successful example -test build here: https://travis-ci.org/git/git/builds/120473209

-

Follow these steps for the initial setup:

-
    -
  1. -

    -Fork https://github.com/git/git to your GitHub account. - You can find detailed instructions how to fork here: - https://help.github.com/articles/fork-a-repo/ -

    -
  2. -
  3. -

    -Open the Travis CI website: https://travis-ci.org -

    -
  4. -
  5. -

    -Press the "Sign in with GitHub" button. -

    -
  6. -
  7. -

    -Grant Travis CI permissions to access your GitHub account. - You can find more information about the required permissions here: - https://docs.travis-ci.com/user/github-oauth-scopes -

    -
  8. -
  9. -

    -Open your Travis CI profile page: https://travis-ci.org/profile -

    -
  10. -
  11. -

    -Enable Travis CI builds for your Git fork. -

    -
  12. -
-

After the initial setup, Travis CI will run whenever you push new changes -to your fork of Git on GitHub. You can monitor the test state of all your -branches here: https://travis-ci.org/<Your GitHub handle>/git/branches

-

If a branch did not pass all test cases then it is marked with a red -cross. In that case you can click on the failing Travis CI job and -scroll all the way down in the log. Find the line "←- Click here to see -detailed test output!" and click on the triangle next to the log line -number to expand the detailed test output. Here is such a failing -example: https://travis-ci.org/git/git/jobs/122676187

-

Fix the problem and push your fix to your Git fork. This will trigger -a new Travis CI build to ensure all tests pass.

-
-
-
-

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.

-

See the DISCUSSION section of git-format-patch(1) for hints on -checking your patch by mailing it to yourself and applying with -git-am(1).

-

While you are at it, check the resulting commit log message from -a trial run of applying the patch. If what is in the resulting -commit is not exactly what you would want to see, 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 <torvalds@g5.osdl.org>
-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, KMail, GMail

-

See the MUA-SPECIFIC HINTS section of git-format-patch(1).

-
-
-

Gnus

-

"|" in the *Summary* buffer can be used to pipe the current -message to an external program, and this is a handy way to drive -git am. However, if the message is MIME encoded, what is -piped into the program is the representation you see in your -*Article* buffer after unwrapping MIME. This is often not what -you would want for two reasons. It tends to screw up non ASCII -characters (most notably in people’s names), and also -whitespaces (fatal in patches). Running "C-u g" to display the -message in raw form before using "|" to run the pipe can work -this problem around.

-
-
-
-
-

- - - + + + + + + + +Submitting Patches + + + + + + +
+
+

Guidelines

+
+
+

Here are some guidelines for contributing back to this +project. There is also a step-by-step tutorial +available which covers many of these same guidelines.

+
+
+

A typical life cycle of a patch series

+
+

To help us understand the reason behind various guidelines given later +in the document, first let’s understand how the life cycle of a +typical patch series for this project goes.

+
+
+
    +
  1. +

    You come up with an itch. You code it up. You do not need any +pre-authorization from the project to do so.

    +
    +

    Your patches will be reviewed by other contributors on the mailing +list, and the reviews will be done to assess the merit of various +things, like the general idea behind your patch (including "is it +solving a problem worth solving in the first place?"), the reason +behind the design of the solution, and the actual implementation. +The guidelines given here are there to help your patches by making +them easier to understand by the reviewers.

    +
    +
  2. +
  3. +

    You send the patches to the list and cc people who may need to know +about the change. Your goal is not necessarily to convince others +that what you are building is good. Your goal is to get help in +coming up with a solution for the "itch" that is better than what +you can build alone.

    +
    +

    The people who may need to know are the ones who worked on the code +you are touching. These people happen to be the ones who are +most likely to be knowledgeable enough to help you, but +they have no obligation to help you (i.e. you ask them for help, +you don’t demand). git log -p -- $area_you_are_modifying would +help you find out who they are.

    +
    +
  4. +
  5. +

    You get comments and suggestions for improvements. You may even get +them in an "on top of your change" patch form. You are expected to +respond to them with "Reply-All" on the mailing list, while taking +them into account while preparing an updated set of patches.

    +
  6. +
  7. +

    Polish, refine, and re-send your patches to the list and to the people +who spent their time to improve your patch. Go back to step (2).

    +
  8. +
  9. +

    While the above iterations improve your patches, the maintainer may +pick the patches up from the list and queue them to the seen +branch, in order to make it easier for people to play with it +without having to pick up and apply the patches to their trees +themselves. Being in seen has no other meaning. Specifically, it +does not mean the patch was "accepted" in any way.

    +
  10. +
  11. +

    When the discussion reaches a consensus that the latest iteration of +the patches are in good enough shape, the maintainer includes the +topic in the "What’s cooking" report that are sent out a few times a +week to the mailing list, marked as "Will merge to next." This +decision is primarily made by the maintainer with help from those +who participated in the review discussion.

    +
  12. +
  13. +

    After the patches are merged to the next branch, the discussion +can still continue to further improve them by adding more patches on +top, but by the time a topic gets merged to next, it is expected +that everybody agrees that the scope and the basic direction of the +topic are appropriate, so such an incremental updates are limited to +small corrections and polishing. After a topic cooks for some time +(like 7 calendar days) in next without needing further tweaks on +top, it gets merged to the master branch and wait to become part +of the next major release.

    +
  14. +
+
+
+

In the following sections, many techniques and conventions are listed +to help your patches get reviewed effectively in such a life cycle.

+
+
+
+

Choose a starting point.

+
+

As a preliminary step, you must first choose a starting point for your +work. Typically this means choosing a branch, although technically +speaking it is actually a particular commit (typically the HEAD, or tip, +of the branch).

+
+
+

There are several important branches to be aware of. Namely, there are +four integration branches as discussed in gitworkflows(7):

+
+
+
    +
  • +

    maint

    +
  • +
  • +

    master

    +
  • +
  • +

    next

    +
  • +
  • +

    seen

    +
  • +
+
+
+

The branches lower on the list are typically descendants of the ones +that come before it. For example, maint is an "older" branch than +master because master usually has patches (commits) on top of +maint.

+
+
+

There are also "topic" branches, which contain work from other +contributors. Topic branches are created by the Git maintainer (in +their fork) to organize the current set of incoming contributions on +the mailing list, and are itemized in the regular "What’s cooking in +git.git" announcements. To find the tip of a topic branch, run git log +--first-parent master..seen and look for the merge commit. The second +parent of this commit is the tip of the topic branch.

+
+
+

There is one guiding principle for choosing the right starting point: in +general, always base your work on the oldest integration branch that +your change is relevant to (see "Merge upwards" in +gitworkflows(7)). What this principle means is that for the +vast majority of cases, the starting point for new work should be the +latest HEAD commit of maint or master based on the following cases:

+
+
+
    +
  • +

    If you are fixing bugs in the released version, use maint as the +starting point (which may mean you have to fix things without using +new API features on the cutting edge that recently appeared in +master but were not available in the released version).

    +
  • +
  • +

    Otherwise (such as if you are adding new features) use master.

    +
  • +
+
+
+ + + + + +
+
Note
+
+In exceptional cases, a bug that was introduced in an old +version may have to be fixed for users of releases that are much older +than the recent releases. git describe --contains X may describe +X as v2.30.0-rc2-gXXXXXX for the commit X that introduced the +bug, and the bug may be so high-impact that we may need to issue a new +maintenance release for Git 2.30.x series, when "Git 2.41.0" is the +current release. In such a case, you may want to use the tip of the +maintenance branch for the 2.30.x series, which may be available in the +maint-2.30 branch in the maintainer’s +"broken out" repo. +
+
+
+

This also means that next or seen are inappropriate starting points +for your work, if you want your work to have a realistic chance of +graduating to master. They are simply not designed to be used as a +base for new work; they are only there to make sure that topics in +flight work well together. This is why both next and seen are +frequently re-integrated with incoming patches on the mailing list and +force-pushed to replace previous versions of themselves. A topic that is +literally built on top of next cannot be merged to master without +dragging in all the other topics in next, some of which may not be +ready.

+
+
+

For example, if you are making tree-wide changes, while somebody else is +also making their own tree-wide changes, your work may have severe +overlap with the other person’s work. This situation may tempt you to +use next as your starting point (because it would have the other +person’s work included in it), but doing so would mean you’ll not only +depend on the other person’s work, but all the other random things from +other contributors that are already integrated into next. And as soon +as next is updated with a new version, all of your work will need to +be rebased anyway in order for them to be cleanly applied by the +maintainer.

+
+
+

Under truly exceptional circumstances where you absolutely must depend +on a select few topic branches that are already in next but not in +master, you may want to create your own custom base-branch by forking +master and merging the required topic branches into it. You could then +work on top of this base-branch. But keep in mind that this base-branch +would only be known privately to you. So when you are ready to send +your patches to the list, be sure to communicate how you created it in +your cover letter. This critical piece of information would allow +others to recreate your base-branch on their end in order for them to +try out your work.

+
+
+

Finally, note that some parts of the system have dedicated maintainers +with their own separate source code repositories (see the section +"Subsystems" below).

+
+
+
+

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.

+
+
+

Give an explanation for the change(s) that is detailed enough so +that people can judge if it is good thing to do, without reading +the actual patch text to determine how well the code does what +the explanation promises to do.

+
+
+

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. +That being said, patches which plainly describe the things that +help reviewers check the patch, and future maintainers understand +the code, are the most beautiful patches. Descriptions that summarize +the point in the subject well, and describe the motivation for the +change, the approach taken by the change, and if relevant how this +differs substantially from the prior version, are all good things +to have.

+
+
+

Make sure that you have tests for the bug you are fixing. See +t/README for guidance.

+
+
+

When adding a new feature, make sure that you have new tests to show +the feature triggers the new behavior when it should, and to show the +feature does not trigger when it shouldn’t. After any code change, +make sure that the entire test suite passes. When fixing a bug, make +sure you have new tests that break if somebody else breaks what you +fixed by accident to avoid regression. Also, try merging your work to +next and seen and make sure the tests still pass; topics by others +that are still in flight may have unexpected interactions with what +you are trying to do in your topic.

+
+
+

Pushing to a fork of https://github.com/git/git will use their CI +integration to test your changes on Linux, Mac and Windows. See the +GitHub CI section for details.

+
+
+

Do not forget to update the documentation to describe the updated +behavior and make sure that the resulting documentation set formats +well (try the Documentation/doc-diff script).

+
+
+

We currently have a liberal mixture of US and UK English norms for +spelling and grammar, which is somewhat unfortunate. A huge patch that +touches the files all over the place only to correct the inconsistency +is not welcome, though. Potential clashes with other changes that can +result from such a patch are not worth it. We prefer to gradually +reconcile the inconsistencies in favor of US English, with small and +easily digestible patches, as a side effect of doing some other real +work in the vicinity (e.g. rewriting a paragraph for clarity, while +turning en_UK spelling to en_US). Obvious typographical fixes are much +more welcomed ("teh → "the"), preferably submitted as independent +patches separate from other documentation changes.

+
+
+

Oh, another thing. We are picky about whitespaces. Make sure your +changes do not trigger errors with the sample pre-commit hook shipped +in templates/hooks--pre-commit. To help ensure this does not happen, +run git diff --check on your changes before you commit.

+
+
+
+

Describe your changes well.

+
+

The log message that explains your changes is just as important as the +changes themselves. Your code may be clearly written with in-code +comment to sufficiently explain how it works with the surrounding +code, but those who need to fix or enhance your code in the future +will need to know why your code does what it does, for a few +reasons:

+
+
+
    +
  1. +

    Your code may be doing something differently from what you wanted it +to do. Writing down what you actually wanted to achieve will help +them fix your code and make it do what it should have been doing +(also, you often discover your own bugs yourself, while writing the +log message to summarize the thought behind it).

    +
  2. +
  3. +

    Your code may be doing things that were only necessary for your +immediate needs (e.g. "do X to directories" without implementing or +even designing what is to be done on files). Writing down why you +excluded what the code does not do will help guide future developers. +Writing down "we do X to directories, because directories have +characteristic Y" would help them infer "oh, files also have the same +characteristic Y, so perhaps doing X to them would also make sense?". +Saying "we don’t do the same X to files, because …​" will help them +decide if the reasoning is sound (in which case they do not waste +time extending your code to cover files), or reason differently (in +which case, they can explain why they extend your code to cover +files, too).

    +
  4. +
+
+
+

The goal of your log message is to convey the why behind your change +to help future developers. The reviewers will also make sure that +your proposed log message will serve this purpose well.

+
+
+

The first line of the commit message should be a short description (50 +characters is the soft limit, see DISCUSSION in git-commit(1)), +and should skip the full stop. It is also conventional in most cases to +prefix the first line with "area: " where the area is a filename or +identifier for the general area of the code being modified, e.g.

+
+
+
    +
  • +

    doc: clarify distinction between sign-off and pgp-signing

    +
  • +
  • +

    githooks.txt: improve the intro section

    +
  • +
+
+
+

If in doubt which identifier to use, run git log --no-merges on the +files you are modifying to see the current conventions.

+
+
+

The title sentence after the "area:" prefix omits the full stop at the +end, and its first word is not capitalized (the omission +of capitalization applies only to the word after the "area:" +prefix of the title) unless there is a reason to +capitalize it other than because it is the first word in the sentence. +E.g. "doc: clarify…​", not "doc: Clarify…​", or "githooks.txt: +improve…​", not "githooks.txt: Improve…​". But "refs: HEAD is also +treated as a ref" is correct, as we spell HEAD in all caps even when +it appears in the middle of a sentence.

+
+
+

The body should provide a meaningful commit message, which:

+
+
+
    +
  1. +

    explains the problem the change tries to solve, i.e. what is wrong +with the current code without the change.

    +
  2. +
  3. +

    justifies the way the change solves the problem, i.e. why the +result with the change is better.

    +
  4. +
  5. +

    alternate solutions considered but discarded, if any.

    +
  6. +
+
+
+

The problem statement that describes the status quo is written in the +present tense. Write "The code does X when it is given input Y", +instead of "The code used to do Y when given input X". You do not +have to say "Currently"---the status quo in the problem statement is +about the code without your change, by project convention.

+
+
+

Describe your changes in imperative mood, e.g. "make xyzzy do frotz" +instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy +to do frotz", as if you are giving orders to the codebase to change +its behavior. Try to make sure your explanation can be understood +without external resources. Instead of giving a URL to a mailing list +archive, summarize the relevant points of the discussion.

+
+
+

There are a few reasons why you may want to refer to another commit in +the "more stable" part of the history (i.e. on branches like maint, +master, and next):

+
+
+
    +
  1. +

    A commit that introduced the root cause of a bug you are fixing.

    +
  2. +
  3. +

    A commit that introduced a feature that you are enhancing.

    +
  4. +
  5. +

    A commit that conflicts with your work when you made a trial merge +of your work into next and seen for testing.

    +
  6. +
+
+
+

When you reference a commit on a more stable branch (like master, +maint and next), use the format "abbreviated hash (subject, +date)", like this:

+
+
+
+
        Commit f86a374 (pack-bitmap.c: fix a memleak, 2015-03-30)
+        noticed that ...
+
+
+
+

The "Copy commit reference" command of gitk can be used to obtain this +format (with the subject enclosed in a pair of double-quotes), or this +invocation of git show:

+
+
+
+
        git show -s --pretty=reference <commit>
+
+
+
+

or, on an older version of Git without support for --pretty=reference:

+
+
+
+
        git show -s --date=short --pretty='format:%h (%s, %ad)' <commit>
+
+
+
+
+

Certify your work by adding your Signed-off-by trailer

+
+

To improve tracking of who did what, we ask you to certify that you +wrote the patch or have the right to pass it on under the same license +as ours, by "signing off" your patch. Without sign-off, we cannot +accept your patches.

+
+
+

If (and only if) you certify the below D-C-O:

+
+
+
Developer’s Certificate of Origin 1.1
+
+
+

By making a contribution to this project, I certify that:

+
+
+
    +
  1. +

    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

    +
  2. +
  3. +

    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

    +
  4. +
  5. +

    The contribution was provided directly to me by some other +person who certified (a), (b) or (c) and I have not modified +it.

    +
  6. +
  7. +

    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.

    +
  8. +
+
+
+
+
+

you add a "Signed-off-by" trailer to your commit, that looks like +this:

+
+
+
+
        Signed-off-by: Random J Developer <random@developer.example.org>
+
+
+
+

This line can be added by Git if you run the git-commit command with +the -s option.

+
+
+

Notice that you can place your own Signed-off-by trailer when +forwarding somebody else’s patch with the above rules for +D-C-O. Indeed you are encouraged to do so. Do not forget to +place an in-body "From: " line at the beginning to properly attribute +the change to its true author (see (2) above).

+
+
+

This procedure originally came from the Linux kernel project, so our +rule is quite similar to theirs, but what exactly it means to sign-off +your patch differs from project to project, so it may be different +from that of the project you are accustomed to.

+
+
+

Please use a known identity in the Signed-off-by trailer, since we cannot +accept anonymous contributions. It is common, but not required, to use some form +of your real name. We realize that some contributors are not comfortable doing +so or prefer to contribute under a pseudonym or preferred name and we can accept +your patch either way, as long as the name and email you use are distinctive, +identifying, and not misleading.

+
+
+

The goal of this policy is to allow us to have sufficient information to contact +you if questions arise about your contribution.

+
+
+

If you like, you can put extra trailers at the end:

+
+
+
    +
  1. +

    Reported-by: is used to credit someone who found the bug that +the patch attempts to fix.

    +
  2. +
  3. +

    Acked-by: says that the person who is more familiar with the area +the patch attempts to modify liked the patch.

    +
  4. +
  5. +

    Reviewed-by:, unlike the other trailers, can only be offered by the +reviewers themselves when they are completely satisfied with the +patch after a detailed analysis.

    +
  6. +
  7. +

    Tested-by: is used to indicate that the person applied the patch +and found it to have the desired effect.

    +
  8. +
  9. +

    Co-authored-by: is used to indicate that people exchanged drafts +of a patch before submitting it.

    +
  10. +
  11. +

    Helped-by: is used to credit someone who suggested ideas for +changes without providing the precise changes in patch form.

    +
  12. +
  13. +

    Mentored-by: is used to credit someone with helping develop a +patch as part of a mentorship program (e.g., GSoC or Outreachy).

    +
  14. +
  15. +

    Suggested-by: is used to credit someone with suggesting the idea +for a patch.

    +
  16. +
+
+
+

While you can also create your own trailer if the situation warrants it, we +encourage you to instead use one of the common trailers in this project +highlighted above.

+
+
+

Only capitalize the very first letter of the trailer, i.e. favor +"Signed-off-by" over "Signed-Off-By" and "Acked-by:" over "Acked-By".

+
+
+
+

Use of Artificial Intelligence (AI)

+
+

The Developer’s Certificate of Origin requires contributors to certify +that they know the origin of their contributions to the project and +that they have the right to submit it under the project’s license. +It’s not yet clear that this can be legally satisfied when submitting +significant amount of content that has been generated by AI tools.

+
+
+

Another issue with AI generated content is that AIs still often +hallucinate or just produce bad code, commit messages, documentation +or output, even when you point out their mistakes.

+
+
+

To avoid these issues, we will reject anything that looks AI +generated, that sounds overly formal or bloated, that looks like AI +slop, that looks good on the surface but makes no sense, or that +senders don’t understand or cannot explain.

+
+
+

We strongly recommend using AI tools carefully and responsibly.

+
+
+

Contributors would often benefit more from AI by using it to guide and +help them step by step towards producing a solution by themselves +rather than by asking for a full solution that they would then mostly +copy-paste. They can also use AI to help with debugging, or with +checking for obvious mistakes, things that can be improved, things +that don’t match our style, guidelines or our feedback, before sending +it to us.

+
+
+
+

Generate your patch using Git tools out of your commits.

+
+

Git based diff tools 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 add commented out debugging code, +or include any extra files which do not relate to what your patch +is trying to achieve. Make sure to review +your patch after generating it, to ensure accuracy. Before +sending out, please make sure it cleanly applies to the starting point you +have chosen in the "Choose a starting point" section.

+
+
+ + + + + +
+
Note
+
+From the perspective of those reviewing your patch, the master +branch is the default expected starting point. So if you have chosen a +different starting point, please communicate this choice in your cover +letter. +
+
+
+
+

Sending your patches.

+
+

Choosing your reviewers

+
+ + + + + +
+
Note
+
+Patches that may be +security relevant should be submitted privately to the Git Security +mailing list[1], instead of the public mailing list. +
+
+
+

Send your patch with "To:" set to the mailing list, with "cc:" listing +people who are involved in the area you are touching (the git-contacts +script in contrib/contacts/[2] can help to +identify them), to solicit comments and reviews. Also, when you made +trial merges of your topic to next and seen, you may have noticed +work by others conflicting with your changes. There is a good possibility +that these people may know the area you are touching well.

+
+
+

If you are using send-email, you can feed it the output of git-contacts like +this:

+
+
+
+
        git send-email --cc-cmd='perl contrib/contacts/git-contacts' feature/*.patch
+
+
+
+

After the list reached a consensus that it is a good idea to apply the +patch, re-send it with "To:" set to the maintainer[3] +and "cc:" the list[4] for inclusion. This is especially relevant +when the maintainer did not heavily participate in the discussion and +instead left the review to trusted others.

+
+
+

Do not forget to add trailers such as Acked-by:, Reviewed-by: and +Tested-by: lines as necessary to credit people who helped your +patch, and "cc:" them when sending such a final version for inclusion.

+
+
+
+

format-patch and send-email

+
+

Learn to use format-patch and send-email if possible. These commands +are optimized for the workflow of sending patches, avoiding many ways +your existing e-mail client (often optimized for "multipart/*" MIME +type e-mails) might render your patches unusable.

+
+
+ + + + + +
+
Note
+
+Here we outline the procedure using format-patch and +send-email, but you can instead use GitGitGadget to send in your +patches (see MyFirstContribution). +
+
+
+

People on the Git mailing list need to be able to read and +comment on the changes you are submitting. It is important for +a developer to be able to "quote" your changes, using standard +e-mail tools, so that they may comment on specific portions of +your code. For this reason, each patch should be submitted +"inline" in a separate message.

+
+
+

All subsequent versions of a patch series and other related patches should be +grouped into their own e-mail thread to help readers find all parts of the +series. To that end, send them as replies to either an additional "cover +letter" message (see below), the first patch, or the respective preceding patch. +Here is a step-by-step guide on +how to submit updated versions of a patch series.

+
+
+

If your log message (including your name on the +Signed-off-by trailer) is not writable in ASCII, make sure that +you send off a message in the correct encoding.

+
+
+ + + + + +
+
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. Use of markers in addition to PATCH within +the brackets to describe the nature of the patch is also +encouraged. E.g. [RFC PATCH] (where RFC stands for "request for +comments") is often used to indicate a patch needs further +discussion before being accepted, [PATCH v2], [PATCH v3] etc. +are often seen when you are sending an update to what you have +previously sent.

+
+
+

The 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 trailers, 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. +To change the default "[PATCH]" in the subject to "[<text>]", use +git format-patch --subject-prefix=<text>. As a shortcut, you +can use --rfc instead of --subject-prefix="RFC PATCH", or +-v <n> instead of --subject-prefix="PATCH v<n>".

+
+
+

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 line and the diffstat. For +patches requiring multiple iterations of review and discussion, +an explanation of changes between each iteration can be kept in +Git-notes and inserted automatically following the three-dash +line via git format-patch --notes.

+
+
+

This is EXPERIMENTAL.

+
+
+

When sending a topic, you can optionally propose a topic name and/or a +one-paragraph summary that should appear in the "What’s cooking" +report when it is picked up to explain the topic. If you choose to do +so, please write a 2-5 line paragraph that will fit well in our +release notes (see many bulleted entries in the +Documentation/RelNotes/* files for examples), and make it the first +(or second, if including a suggested topic name) paragraph of the +cover letter. If suggesting a topic name, use the format +"XX/your-topic-name", where "XX" is a stand-in for the primary +author’s initials, and "your-topic-name" is a brief, dash-delimited +description of what your topic does. For a single-patch series, use +the space between the three-dash line and the diffstat, as described +earlier.

+
+
+

If your patch series is part of a larger effort spanning multiple +patch series, briefly describe the broader goal, and state where the +current series fits into that goal. If you are suggesting a topic +name as in section above, consider +"XX/the-broader-goal-part-one", "XX/the-broader-goal-part-two", and so +on.

+
+
+

Do not attach the patch as a MIME attachment, compressed or not. +Do not let your e-mail client send quoted-printable. Do not let +your e-mail client send format=flowed which would destroy +whitespaces in your patches. 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. 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.

+
+
+
+
+

Handling Conflicts and Iterating Patches

+
+

When revising changes made to your patches, it’s important to +acknowledge the possibility of conflicts with other ongoing topics. To +navigate these potential conflicts effectively, follow the recommended +steps outlined below:

+
+
+
    +
  1. +

    Build on a suitable base branch, see the section above, +and format-patch the series. If you are doing "rebase -i" in-place to +update from the previous round, this will reuse the previous base so +(2) and (3) may become trivial.

    +
  2. +
  3. +

    Find the base of where the last round was queued

    +
    +
    +
    $ mine='kn/ref-transaction-symref'
    +$ git checkout "origin/seen^{/^Merge branch '$mine'}...master"
    +
    +
    +
  4. +
  5. +

    Apply your format-patch result. There are two cases

    +
    +
      +
    1. +

      Things apply cleanly and tests fine. Go to (4).

      +
    2. +
    3. +

      Things apply cleanly but does not build or test fails, or things do +not apply cleanly.

      +
      +

      In the latter case, you have textual or semantic conflicts coming from +the difference between the old base and the base you used to build in +(1). Identify what caused the breakages (e.g., a topic or two may have +merged since the base used by (2) until the base used by (1)).

      +
      +
      +

      Check out the latest origin/master (which may be newer than the base +used by (2)), "merge --no-ff" the topics you newly depend on in there, +and use the result of the merge(s) as the base, rebuild the series and +test again. Run format-patch from the last such merges to the tip of +your topic. If you did

      +
      +
      +
      +
      $ git checkout origin/master
      +$ git merge --no-ff --into-name kn/ref-transaction-symref fo/obar
      +$ git merge --no-ff --into-name kn/ref-transaction-symref ba/zqux
      +... rebuild the topic ...
      +
      +
      +
      +

      Then you’d just format your topic above these "preparing the ground" +merges, e.g.

      +
      +
      +
      +
      $ git format-patch "HEAD^{/^Merge branch 'ba/zqux'}"..HEAD
      +
      +
      +
      +

      Do not forget to write in the cover letter you did this, including the +topics you have in your base on top of master. Then go to (4).

      +
      +
    4. +
    +
    +
  6. +
  7. +

    Make a trial merge of your topic into next and seen, e.g.

    +
    +
    +
    $ git checkout --detach 'origin/seen'
    +$ git revert -m 1 <the merge of the previous iteration into seen>
    +$ git merge kn/ref-transaction-symref
    +
    +
    +
    +

    The "revert" is needed if the previous iteration of your topic is +already in seen (like in this case). You could choose to rebuild +master..origin/seen from scratch while excluding your previous +iteration, which may emulate what happens on the maintainers end more +closely.

    +
    +
    +

    This trial merge may conflict. It is primarily to see what conflicts +other topics may have with your topic. In other words, you do not +have to depend on it to make your topic work on master. It may +become the job of the other topic owners to resolve conflicts if your +topic goes to next before theirs.

    +
    +
    +

    Make a note on what conflict you saw in the cover letter. You do not +necessarily have to resolve them, but it would be a good opportunity to +learn what others are doing in related areas.

    +
    +
    +
    +
    $ git checkout --detach 'origin/next'
    +$ git merge kn/ref-transaction-symref
    +
    +
    +
    +

    This is to see what conflicts your topic has with other topics that are +already cooking. This should not conflict if (3)-2 prepared a base on +top of updated master plus dependent topics taken from next. Unless +the context is severe (one way to tell is try the same trial merge with +your old iteration, which may conflict in a similar way), expect that it +will be handled on maintainers end (if it gets unmanageable, I’ll ask to +rebase when I receive your patches).

    +
    +
  8. +
+
+
+
+
+
+

Subsystems with dedicated maintainers

+
+
+

Some parts of the system have dedicated maintainers with their own +repositories.

+
+
+
    +
  • +

    git-gui/ comes from the git-gui project, maintained by Johannes Sixt:

    +
    +
    +
    https://github.com/j6t/git-gui
    +
    +
    +
    +
    +
    Contibutions should go via the git mailing list.
    +
    +
    +
  • +
  • +

    gitk-git/ comes from the gitk project, maintained by Johannes Sixt:

    +
    +
    +
    https://github.com/j6t/gitk
    +
    +
    +
    +
    +
    Contibutions should go via the git mailing list.
    +
    +
    +
  • +
  • +

    po/ comes from the localization coordinator, Jiang Xin:

    +
    +
    +
    https://github.com/git-l10n/git-po/
    +
    +
    +
  • +
+
+
+

Patches to these parts should be based on their trees.

+
+
+
    +
  • +

    The "Git documentation translations" project, led by Jean-Noël +Avila, translates our documentation pages. Their work products are +maintained separately from this project, not as part of our tree:

    +
    +
    +
    https://github.com/jnavila/git-manpages-l10n/
    +
    +
    +
  • +
+
+
+
+
+

GitHub CI

+
+
+

With an account at GitHub, you can use GitHub CI to test your changes +on Linux, Mac and Windows. See +https://github.com/git/git/actions/workflows/main.yml for examples of +recent CI runs.

+
+
+

Follow these steps for the initial setup:

+
+
+
    +
  1. +

    Fork https://github.com/git/git to your GitHub account. +You can find detailed instructions how to fork here: +https://help.github.com/articles/fork-a-repo/

    +
  2. +
+
+
+

After the initial setup, CI will run whenever you push new changes +to your fork of Git on GitHub. You can monitor the test state of all your +branches here: https://github.com/<Your GitHub handle>/git/actions/workflows/main.yml

+
+
+

If a branch does not pass all test cases then it will be marked with a +red x, instead of a green check. In that case, you can click on the +failing job and navigate to "ci/run-build-and-tests.sh" and/or +"ci/print-test-failures.sh". You can also download "Artifacts" which +are zip archives containing tarred (or zipped) archives with test data +relevant for debugging.

+
+
+

Then fix the problem and push your fix to your GitHub fork. This will +trigger a new CI build to ensure all tests pass.

+
+
+
+
+

MUA specific hints

+
+
+

Some of the 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.

+
+
+

See the DISCUSSION section of git-format-patch(1) for hints on +checking your patch by mailing it to yourself and applying with +git-am(1).

+
+
+

While you are at it, check the resulting commit log message from +a trial run of applying the patch. If what is in the resulting +commit is not exactly what you would want to see, 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 <torvalds@g5.osdl.org>
+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, KMail, GMail

+
+

See the MUA-SPECIFIC HINTS section of git-format-patch(1).

+
+
+
+

Gnus

+
+

"|" in the *Summary* buffer can be used to pipe the current +message to an external program, and this is a handy way to drive +git am. However, if the message is MIME encoded, what is +piped into the program is the representation you see in your +*Article* buffer after unwrapping MIME. This is often not what +you would want for two reasons. It tends to screw up non-ASCII +characters (most notably in people’s names), and also +whitespaces (fatal in patches). Running "C-u g" to display the +message in raw form before using "|" to run the pipe can work +this problem around.

+
+
+
+
+
+
+
+
+1. The Git Security mailing list: git-security@googlegroups.com +
+
+2. Scripts under `contrib/` are not part of the core `git` binary and must be called directly. Clone the Git codebase and run `perl contrib/contacts/git-contacts`. +
+
+3. The current maintainer: gitster@pobox.com +
+
+4. The mailing list: git@vger.kernel.org +
+
+ + + \ No newline at end of file diff --git a/SubmittingPatches.txt b/SubmittingPatches.txt deleted file mode 100644 index ec8b20514..000000000 --- a/SubmittingPatches.txt +++ /dev/null @@ -1,569 +0,0 @@ -Submitting Patches -================== - -== Guidelines - -Here are some guidelines for people who want to contribute their code -to this software. - -[[base-branch]] -=== Decide what to base your work on. - -In general, always base your work on the oldest branch that your -change is relevant to. - -* A bugfix should be based on `maint` in general. If the bug is not - present in `maint`, base it on `master`. For a bug that's not yet - in `master`, find the topic that introduces the regression, and - base your work on the tip of the topic. - -* A new feature should be based on `master` in general. If the new - feature depends on a topic that is in `pu`, but not in `master`, - base your work on the tip of that topic. - -* Corrections and enhancements to a topic not yet in `master` should - be based on the tip of that topic. If the topic has not been merged - to `next`, it's alright to add a note to squash minor corrections - into the series. - -* In the exceptional case that a new feature depends on several topics - not in `master`, start working on `next` or `pu` privately and send - out patches for discussion. Before the final merge, you may have to - wait until some of the dependent topics graduate to `master`, and - rebase your work. - -* Some parts of the system have dedicated maintainers with their own - repositories (see the section "Subsystems" below). Changes to - these parts should be based on their trees. - -To find the tip of a topic branch, run `git log --first-parent -master..pu` and look for the merge commit. The second parent of this -commit is the tip of the topic branch. - -[[separate-commits]] -=== 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. - -Give an explanation for the change(s) that is detailed enough so -that people can judge if it is good thing to do, without reading -the actual patch text to determine how well the code does what -the explanation promises to do. - -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. -That being said, patches which plainly describe the things that -help reviewers check the patch, and future maintainers understand -the code, are the most beautiful patches. Descriptions that summarize -the point in the subject well, and describe the motivation for the -change, the approach taken by the change, and if relevant how this -differs substantially from the prior version, are all good things -to have. - -Make sure that you have tests for the bug you are fixing. See -`t/README` for guidance. - -[[tests]] -When adding a new feature, make sure that you have new tests to show -the feature triggers the new behavior when it should, and to show the -feature does not trigger when it shouldn't. After any code change, make -sure that the entire test suite passes. - -If you have an account at GitHub (and you can get one for free to work -on open source projects), you can use their Travis CI integration to -test your changes on Linux, Mac (and hopefully soon Windows). See -GitHub-Travis CI hints section for details. - -Do not forget to update the documentation to describe the updated -behavior and make sure that the resulting documentation set formats -well (try the Documentation/doc-diff script). - -We currently have a liberal mixture of US and UK English norms for -spelling and grammar, which is somewhat unfortunate. A huge patch that -touches the files all over the place only to correct the inconsistency -is not welcome, though. Potential clashes with other changes that can -result from such a patch are not worth it. We prefer to gradually -reconcile the inconsistencies in favor of US English, with small and -easily digestible patches, as a side effect of doing some other real -work in the vicinity (e.g. rewriting a paragraph for clarity, while -turning en_UK spelling to en_US). Obvious typographical fixes are much -more welcomed ("teh -> "the"), preferably submitted as independent -patches separate from other documentation changes. - -[[whitespace-check]] -Oh, another thing. We are picky about whitespaces. Make sure your -changes do not trigger errors with the sample pre-commit hook shipped -in `templates/hooks--pre-commit`. To help ensure this does not happen, -run `git diff --check` on your changes before you commit. - -[[describe-changes]] -=== Describe your changes well. - -The first line of the commit message should be a short description (50 -characters is the soft limit, see DISCUSSION in linkgit:git-commit[1]), -and should skip the full stop. It is also conventional in most cases to -prefix the first line with "area: " where the area is a filename or -identifier for the general area of the code being modified, e.g. - -* doc: clarify distinction between sign-off and pgp-signing -* githooks.txt: improve the intro section - -If in doubt which identifier to use, run `git log --no-merges` on the -files you are modifying to see the current conventions. - -[[summary-section]] -It's customary to start the remainder of the first line after "area: " -with a lower-case letter. E.g. "doc: clarify...", not "doc: -Clarify...", or "githooks.txt: improve...", not "githooks.txt: -Improve...". - -[[meaningful-message]] -The body should provide a meaningful commit message, which: - -. explains the problem the change tries to solve, i.e. what is wrong - with the current code without the change. - -. justifies the way the change solves the problem, i.e. why the - result with the change is better. - -. alternate solutions considered but discarded, if any. - -[[imperative-mood]] -Describe your changes in imperative mood, e.g. "make xyzzy do frotz" -instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy -to do frotz", as if you are giving orders to the codebase to change -its behavior. Try to make sure your explanation can be understood -without external resources. Instead of giving a URL to a mailing list -archive, summarize the relevant points of the discussion. - -[[commit-reference]] -If you want to reference a previous commit in the history of a stable -branch, use the format "abbreviated sha1 (subject, date)", -with the subject enclosed in a pair of double-quotes, like this: - -.... - Commit f86a374 ("pack-bitmap.c: fix a memleak", 2015-03-30) - noticed that ... -.... - -The "Copy commit summary" command of gitk can be used to obtain this -format, or this invocation of `git show`: - -.... - git show -s --date=short --pretty='format:%h ("%s", %ad)' -.... - -[[git-tools]] -=== Generate your patch using Git tools out of your commits. - -Git based diff tools 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. - -[[review-patch]] -Please make sure your patch does not add commented out debugging code, -or include any extra files which do not relate to what your patch -is trying to achieve. 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. - -[[send-patches]] -=== Sending your patches. - -:security-ml: footnoteref:[security-ml,The Git Security mailing list: git-security@googlegroups.com] - -Before sending any patches, please note that patches that may be -security relevant should be submitted privately to the Git Security -mailing list{security-ml}, instead of the public mailing list. - -Learn to use format-patch and send-email if possible. These commands -are optimized for the workflow of sending patches, avoiding many ways -your existing e-mail client that is optimized for "multipart/*" mime -type e-mails to corrupt and render your patches unusable. - -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, each patch should be submitted -"inline" in a separate message. - -Multiple related patches should be grouped into their own e-mail -thread to help readers find all parts of the series. To that end, -send them as replies to either an additional "cover letter" message -(see below), the first patch, or the respective preceding patch. - -If your log message (including your name on the -Signed-off-by line) is not writable in ASCII, make sure that -you send off a message in the correct encoding. - -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. Use of markers in addition to PATCH within -the brackets to describe the nature of the patch is also -encouraged. E.g. [RFC PATCH] (where RFC stands for "request for -comments") is often used to indicate a patch needs further -discussion before being accepted, [PATCH v2], [PATCH v3] etc. -are often seen when you are sending an update to what you have -previously sent. - -The `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. -To change the default "[PATCH]" in the subject to "[]", use -`git format-patch --subject-prefix=`. As a shortcut, you -can use `--rfc` instead of `--subject-prefix="RFC PATCH"`, or -`-v ` instead of `--subject-prefix="PATCH v"`. - -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 line and the diffstat. For -patches requiring multiple iterations of review and discussion, -an explanation of changes between each iteration can be kept in -Git-notes and inserted automatically following the three-dash -line via `git format-patch --notes`. - -[[attachment]] -Do not attach the patch as a MIME attachment, compressed or not. -Do not let your e-mail client send quoted-printable. Do not let -your e-mail client send format=flowed which would destroy -whitespaces in your patches. 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. - -[[pgp-signature]] -Do not PGP sign your patch. 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. - -:security-ml-ref: footnoteref:[security-ml] - -As mentioned at the beginning of the section, patches that may be -security relevant should not be submitted to the public mailing list -mentioned below, but should instead be sent privately to the Git -Security mailing list{security-ml-ref}. - -Send your patch with "To:" set to the mailing list, with "cc:" listing -people who are involved in the area you are touching (the `git -contacts` command in `contrib/contacts/` can help to -identify them), to solicit comments and reviews. - -:current-maintainer: footnote:[The current maintainer: gitster@pobox.com] -:git-ml: footnote:[The mailing list: git@vger.kernel.org] - -After the list reached a consensus that it is a good idea to apply the -patch, re-send it with "To:" set to the maintainer{current-maintainer} and "cc:" the -list{git-ml} for inclusion. - -Do not forget to add trailers such as `Acked-by:`, `Reviewed-by:` and -`Tested-by:` lines as necessary to credit people who helped your -patch. - -[[sign-off]] -=== Certify your work by adding your "Signed-off-by: " line - -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 an open-source patch. The rules are -pretty simple: if you can certify the below D-C-O: - -[[dco]] -.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 -.... - -This line can be automatically added by Git if you run the git-commit -command with the -s option. - -Notice that you can place your own Signed-off-by: line when -forwarding somebody else's patch with the above rules for -D-C-O. Indeed you are encouraged to do so. Do not forget to -place an in-body "From: " line at the beginning to properly attribute -the change to its true author (see (2) above). - -[[real-name]] -Also notice that a real name is used in the Signed-off-by: line. Please -don't hide your real name. - -[[commit-trailers]] -If you like, you can put extra tags at the end: - -. `Reported-by:` is used to credit someone who found the bug that - the patch attempts to fix. -. `Acked-by:` says that the person who is more familiar with the area - the patch attempts to modify liked the patch. -. `Reviewed-by:`, unlike the other tags, can only be offered by the - reviewer and means that she is completely satisfied that the patch - is ready for application. It is usually offered only after a - detailed review. -. `Tested-by:` is used to indicate that the person applied the patch - and found it to have the desired effect. - -You can also create your own tag or use one that's in common usage -such as "Thanks-to:", "Based-on-patch-by:", or "Mentored-by:". - -== Subsystems with dedicated maintainers - -Some parts of the system have dedicated maintainers with their own -repositories. - -- 'git-gui/' comes from git-gui project, maintained by Pat Thoyts: - - git://repo.or.cz/git-gui.git - -- 'gitk-git/' comes from Paul Mackerras's gitk project: - - git://ozlabs.org/~paulus/gitk - -- 'po/' comes from the localization coordinator, Jiang Xin: - - https://github.com/git-l10n/git-po/ - -Patches to these parts should be based on their trees. - -[[patch-flow]] -== An ideal patch flow - -Here is an ideal patch flow for this project the current maintainer -suggests to the contributors: - -. You come up with an itch. You code it up. - -. Send it to the list and cc people who may need to know about - the change. -+ -The people who may need to know are the ones whose code you -are butchering. These people happen to be the ones who are -most likely to be knowledgeable enough to help you, but -they have no obligation to help you (i.e. you ask for help, -don't demand). +git log -p {litdd} _$area_you_are_modifying_+ would -help you find out who they are. - -. You get comments and suggestions for improvements. You may - even get them in an "on top of your change" patch form. - -. Polish, refine, and re-send to the list and the people who - spend their time to improve your patch. Go back to step (2). - -. The list forms consensus that the last round of your patch is - good. Send it to the maintainer and cc the list. - -. A topic branch is created with the patch and is merged to `next`, - and cooked further and eventually graduates to `master`. - -In any time between the (2)-(3) cycle, the maintainer may pick it up -from the list and queue it to `pu`, in order to make it easier for -people play with it without having to pick up and apply the patch to -their trees themselves. - -[[patch-status]] -== Know the status of your patch after submission - -* You can use Git itself to find out when your patch is merged in - master. `git pull --rebase` will automatically skip already-applied - patches, and will let you know. This works only if you rebase on top - of the branch in which your patch has been merged (i.e. it will not - tell you if your patch is merged in pu if you rebase on top of - master). - -* Read the Git mailing list, the maintainer regularly posts messages - entitled "What's cooking in git.git" and "What's in git.git" giving - the status of various proposed changes. - -[[travis]] -== GitHub-Travis CI hints - -With an account at GitHub (you can get one for free to work on open -source projects), you can use Travis CI to test your changes on Linux, -Mac (and hopefully soon Windows). You can find a successful example -test build here: https://travis-ci.org/git/git/builds/120473209 - -Follow these steps for the initial setup: - -. Fork https://github.com/git/git to your GitHub account. - You can find detailed instructions how to fork here: - https://help.github.com/articles/fork-a-repo/ - -. Open the Travis CI website: https://travis-ci.org - -. Press the "Sign in with GitHub" button. - -. Grant Travis CI permissions to access your GitHub account. - You can find more information about the required permissions here: - https://docs.travis-ci.com/user/github-oauth-scopes - -. Open your Travis CI profile page: https://travis-ci.org/profile - -. Enable Travis CI builds for your Git fork. - -After the initial setup, Travis CI will run whenever you push new changes -to your fork of Git on GitHub. You can monitor the test state of all your -branches here: https://travis-ci.org/____/git/branches - -If a branch did not pass all test cases then it is marked with a red -cross. In that case you can click on the failing Travis CI job and -scroll all the way down in the log. Find the line "<-- Click here to see -detailed test output!" and click on the triangle next to the log line -number to expand the detailed test output. Here is such a failing -example: https://travis-ci.org/git/git/jobs/122676187 - -Fix the problem and push your fix to your Git fork. This will trigger -a new Travis CI build to ensure all tests pass. - -[[mua]] -== 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. - -See the DISCUSSION section of linkgit:git-format-patch[1] for hints on -checking your patch by mailing it to yourself and applying with -linkgit:git-am[1]. - -While you are at it, check the resulting commit log message from -a trial run of applying the patch. If what is in the resulting -commit is not exactly what you would want to see, 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, KMail, GMail - -See the MUA-SPECIFIC HINTS section of linkgit:git-format-patch[1]. - -=== Gnus - -"|" in the `*Summary*` buffer can be used to pipe the current -message to an external program, and this is a handy way to drive -`git am`. However, if the message is MIME encoded, what is -piped into the program is the representation you see in your -`*Article*` buffer after unwrapping MIME. This is often not what -you would want for two reasons. It tends to screw up non ASCII -characters (most notably in people's names), and also -whitespaces (fatal in patches). Running "C-u g" to display the -message in raw form before using "|" to run the pipe can work -this problem around. diff --git a/ToolsForGit.adoc b/ToolsForGit.adoc new file mode 100644 index 000000000..a842c1332 --- /dev/null +++ b/ToolsForGit.adoc @@ -0,0 +1,52 @@ +Tools for developing Git +======================== +:sectanchors: + +[[summary]] +== Summary + +This document gathers tips, scripts, and configuration files to help people +working on Git's codebase use their favorite tools while following Git's +coding style. + +[[author]] +=== Author + +The Git community. + +[[table_of_contents]] +== Table of contents + +- <> +- <> + +[[vscode]] +=== Visual Studio Code (VS Code) + +The contrib/vscode/init.sh script creates configuration files that enable +several valuable VS Code features. See contrib/vscode/README.md for more +information on using the script. + +[[emacs]] +=== Emacs + +This is adapted from Linux's suggestion in its CodingStyle document: + +- To follow the rules in CodingGuidelines, it's useful to put the following in +GIT_CHECKOUT/.dir-locals.el, assuming you use cperl-mode: + +---- +;; note the first part is useful for C editing, too +((nil . ((indent-tabs-mode . t) + (tab-width . 8) + (fill-column . 80))) + (cperl-mode . ((cperl-indent-level . 8) + (cperl-extra-newline-before-brace . nil) + (cperl-merge-trailing-else . t)))) +---- + +For a more complete setup, since Git's codebase uses a coding style +similar to the Linux kernel's style, tips given in Linux's CodingStyle +document can be applied here too. + +==== https://www.kernel.org/doc/html/v4.10/process/coding-style.html#you-ve-made-a-mess-of-it diff --git a/ToolsForGit.html b/ToolsForGit.html new file mode 100644 index 000000000..33cdfa64f --- /dev/null +++ b/ToolsForGit.html @@ -0,0 +1,527 @@ + + + + + + + +Tools for developing Git + + + + + + +
+
+

Summary

+
+
+

This document gathers tips, scripts, and configuration files to help people +working on Git’s codebase use their favorite tools while following Git’s +coding style.

+
+
+

Author

+
+

The Git community.

+
+
+
+
+
+

Table of contents

+
+ +
+

Visual Studio Code (VS Code)

+
+

The contrib/vscode/init.sh script creates configuration files that enable +several valuable VS Code features. See contrib/vscode/README.md for more +information on using the script.

+
+
+
+

Emacs

+
+

This is adapted from Linux’s suggestion in its CodingStyle document:

+
+
+
    +
  • +

    To follow the rules in CodingGuidelines, it’s useful to put the following in +GIT_CHECKOUT/.dir-locals.el, assuming you use cperl-mode:

    +
  • +
+
+
+
+
;; note the first part is useful for C editing, too
+((nil . ((indent-tabs-mode . t)
+         (tab-width . 8)
+         (fill-column . 80)))
+         (cperl-mode . ((cperl-indent-level . 8)
+                        (cperl-extra-newline-before-brace . nil)
+                        (cperl-merge-trailing-else . t))))
+
+
+
+

For a more complete setup, since Git’s codebase uses a coding style +similar to the Linux kernel’s style, tips given in Linux’s CodingStyle +document can be applied here too.

+
+ +
+
+
+
+ + + \ No newline at end of file diff --git a/blame-options.adoc b/blame-options.adoc new file mode 100644 index 000000000..1fb948fc7 --- /dev/null +++ b/blame-options.adoc @@ -0,0 +1,151 @@ +-b:: + Show blank SHA-1 for boundary commits. This can also + be controlled via the `blame.blankBoundary` config option. + +--root:: + Do not treat root commits as boundaries. This can also be + controlled via the `blame.showRoot` config option. + +--show-stats:: + Include additional statistics at the end of blame output. + +-L ,:: +-L ::: + Annotate only the line range given by ',', + or by the function name regex ''. + May be specified multiple times. Overlapping ranges are allowed. ++ +'' and '' are optional. `-L ` or `-L ,` spans from +'' to end of file. `-L ,` spans from start of file to ''. ++ +include::line-range-format.adoc[] + +-l:: + Show long rev (Default: off). + +-t:: + Show raw timestamp (Default: off). + +-S :: + Use revisions from revs-file instead of calling linkgit:git-rev-list[1]. + +--reverse ..:: + Walk history forward instead of backward. Instead of showing + the revision in which a line appeared, this shows the last + revision in which a line has existed. This requires a range of + revision like START..END where the path to blame exists in + START. `git blame --reverse START` is taken as `git blame + --reverse START..HEAD` for convenience. + +--first-parent:: + Follow only the first parent commit upon seeing a merge + commit. This option can be used to determine when a line + was introduced to a particular integration branch, rather + than when it was introduced to the history overall. + +-p:: +--porcelain:: + Show in a format designed for machine consumption. + +--line-porcelain:: + Show the porcelain format, but output commit information for + each line, not just the first time a commit is referenced. + Implies --porcelain. + +--incremental:: + Show the result incrementally in a format designed for + machine consumption. + +--encoding=:: + Specifies the encoding used to output author names + and commit summaries. Setting it to `none` makes blame + output unconverted data. For more information see the + discussion about encoding in the linkgit:git-log[1] + manual page. + +--contents :: + Annotate using the contents from the named file, starting from + if it is specified, and HEAD otherwise. You may specify '-' to make + the command read from the standard input for the file contents. + +--date :: + Specifies the format used to output dates. If --date is not + provided, the value of the blame.date config variable is + used. If the blame.date config variable is also not set, the + iso format is used. For supported values, see the discussion + of the --date option at linkgit:git-log[1]. + +--progress:: +--no-progress:: + Progress status is reported on the standard error stream + by default when it is attached to a terminal. This flag + enables progress reporting even if not attached to a + terminal. Can't use `--progress` together with `--porcelain` + or `--incremental`. + +-M[]:: + Detect moved or copied lines within a file. When a commit + moves or copies a block of lines (e.g. the original file + has A and then B, and the commit changes it to B and then + A), the traditional 'blame' algorithm notices only half of + the movement and typically blames the lines that were moved + up (i.e. B) to the parent and assigns blame to the lines that + were moved down (i.e. A) to the child commit. With this + option, both groups of lines are blamed on the parent by + running extra passes of inspection. ++ + is optional but it is the lower bound on the number of +alphanumeric characters that Git must detect as moving/copying +within a file for it to associate those lines with the parent +commit. The default value is 20. + +-C[]:: + In addition to `-M`, detect lines moved or copied from other + files that were modified in the same commit. This is + useful when you reorganize your program and move code + around across files. When this option is given twice, + the command additionally looks for copies from other + files in the commit that creates the file. When this + option is given three times, the command additionally + looks for copies from other files in any commit. ++ + is optional but it is the lower bound on the number of +alphanumeric characters that Git must detect as moving/copying +between files for it to associate those lines with the parent +commit. And the default value is 40. If there are more than one +`-C` options given, the argument of the last `-C` will +take effect. + +--ignore-rev :: + Ignore changes made by the revision when assigning blame, as if the + change never happened. Lines that were changed or added by an ignored + commit will be blamed on the previous commit that changed that line or + nearby lines. This option may be specified multiple times to ignore + more than one revision. If the `blame.markIgnoredLines` config option + is set, then lines that were changed by an ignored commit and attributed to + another commit will be marked with a `?` in the blame output. If the + `blame.markUnblamableLines` config option is set, then those lines touched + by an ignored commit that we could not attribute to another revision are + marked with a '*'. In the porcelain modes, we print 'ignored' and + 'unblamable' on a newline respectively. + +--ignore-revs-file :: + Ignore revisions listed in `file`, which must be in the same format as an + `fsck.skipList`. This option may be repeated, and these files will be + processed after any files specified with the `blame.ignoreRevsFile` config + option. An empty file name, `""`, will clear the list of revs from + previously processed files. + +--color-lines:: + Color line annotations in the default format differently if they come from + the same commit as the preceding line. This makes it easier to distinguish + code blocks introduced by different commits. The color defaults to cyan and + can be adjusted using the `color.blame.repeatedLines` config option. + +--color-by-age:: + Color line annotations depending on the age of the line in the default format. + The `color.blame.highlightRecent` config option controls what color is used for + each range of age. + +-h:: + Show help message. diff --git a/blame-options.txt b/blame-options.txt deleted file mode 100644 index dc41957af..000000000 --- a/blame-options.txt +++ /dev/null @@ -1,114 +0,0 @@ --b:: - Show blank SHA-1 for boundary commits. This can also - be controlled via the `blame.blankboundary` config option. - ---root:: - Do not treat root commits as boundaries. This can also be - controlled via the `blame.showRoot` config option. - ---show-stats:: - Include additional statistics at the end of blame output. - --L ,:: --L ::: - Annotate only the given line range. May be specified multiple times. - Overlapping ranges are allowed. -+ - and are optional. ``-L '' or ``-L ,'' spans from - to end of file. ``-L ,'' spans from start of file to . -+ -include::line-range-format.txt[] - --l:: - Show long rev (Default: off). - --t:: - Show raw timestamp (Default: off). - --S :: - Use revisions from revs-file instead of calling linkgit:git-rev-list[1]. - ---reverse ..:: - Walk history forward instead of backward. Instead of showing - the revision in which a line appeared, this shows the last - revision in which a line has existed. This requires a range of - revision like START..END where the path to blame exists in - START. `git blame --reverse START` is taken as `git blame - --reverse START..HEAD` for convenience. - --p:: ---porcelain:: - Show in a format designed for machine consumption. - ---line-porcelain:: - Show the porcelain format, but output commit information for - each line, not just the first time a commit is referenced. - Implies --porcelain. - ---incremental:: - Show the result incrementally in a format designed for - machine consumption. - ---encoding=:: - Specifies the encoding used to output author names - and commit summaries. Setting it to `none` makes blame - output unconverted data. For more information see the - discussion about encoding in the linkgit:git-log[1] - manual page. - ---contents :: - When is not specified, the command annotates the - changes starting backwards from the working tree copy. - This flag makes the command pretend as if the working - tree copy has the contents of the named file (specify - `-` to make the command read from the standard input). - ---date :: - Specifies the format used to output dates. If --date is not - provided, the value of the blame.date config variable is - used. If the blame.date config variable is also not set, the - iso format is used. For supported values, see the discussion - of the --date option at linkgit:git-log[1]. - ---[no-]progress:: - Progress status is reported on the standard error stream - by default when it is attached to a terminal. This flag - enables progress reporting even if not attached to a - terminal. Can't use `--progress` together with `--porcelain` - or `--incremental`. - --M[]:: - Detect moved or copied lines within a file. When a commit - moves or copies a block of lines (e.g. the original file - has A and then B, and the commit changes it to B and then - A), the traditional 'blame' algorithm notices only half of - the movement and typically blames the lines that were moved - up (i.e. B) to the parent and assigns blame to the lines that - were moved down (i.e. A) to the child commit. With this - option, both groups of lines are blamed on the parent by - running extra passes of inspection. -+ - is optional but it is the lower bound on the number of -alphanumeric characters that Git must detect as moving/copying -within a file for it to associate those lines with the parent -commit. The default value is 20. - --C[]:: - In addition to `-M`, detect lines moved or copied from other - files that were modified in the same commit. This is - useful when you reorganize your program and move code - around across files. When this option is given twice, - the command additionally looks for copies from other - files in the commit that creates the file. When this - option is given three times, the command additionally - looks for copies from other files in any commit. -+ - is optional but it is the lower bound on the number of -alphanumeric characters that Git must detect as moving/copying -between files for it to associate those lines with the parent -commit. And the default value is 40. If there are more than one -`-C` options given, the argument of the last `-C` will -take effect. - --h:: - Show help message. diff --git a/cmds-ancillaryinterrogators.adoc b/cmds-ancillaryinterrogators.adoc new file mode 100644 index 000000000..f13a36172 --- /dev/null +++ b/cmds-ancillaryinterrogators.adoc @@ -0,0 +1,51 @@ +linkgit:git-annotate[1]:: + Annotate file lines with commit information. + +linkgit:git-blame[1]:: + Show what revision and author last modified each line of a file. + +linkgit:git-bugreport[1]:: + Collect information for user to file a bug report. + +linkgit:git-count-objects[1]:: + Count unpacked number of objects and their disk consumption. + +linkgit:git-diagnose[1]:: + Generate a zip archive of diagnostic information. + +linkgit:git-difftool[1]:: + Show changes using common diff tools. + +linkgit:git-fsck[1]:: + Verifies the connectivity and validity of the objects in the database. + +linkgit:git-help[1]:: + Display help information about Git. + +linkgit:git-instaweb[1]:: + Instantly browse your working repository in gitweb. + +linkgit:git-merge-tree[1]:: + Perform merge without touching index or working tree. + +linkgit:git-rerere[1]:: + Reuse recorded resolution of conflicted merges. + +linkgit:git-show-branch[1]:: + Show branches and their commits. + +linkgit:git-verify-commit[1]:: + Check the GPG signature of commits. + +linkgit:git-verify-tag[1]:: + Check the GPG signature of tags. + +linkgit:git-version[1]:: + Display version information about Git. + +linkgit:git-whatchanged[1]:: + Show logs with differences each commit introduces. + +linkgit:gitweb[1]:: + Git web interface (web frontend to Git repositories). + diff --git a/cmds-ancillaryinterrogators.txt b/cmds-ancillaryinterrogators.txt deleted file mode 100644 index 019325934..000000000 --- a/cmds-ancillaryinterrogators.txt +++ /dev/null @@ -1,42 +0,0 @@ -linkgit:git-annotate[1]:: - Annotate file lines with commit information. - -linkgit:git-blame[1]:: - Show what revision and author last modified each line of a file. - -linkgit:git-count-objects[1]:: - Count unpacked number of objects and their disk consumption. - -linkgit:git-difftool[1]:: - Show changes using common diff tools. - -linkgit:git-fsck[1]:: - Verifies the connectivity and validity of the objects in the database. - -linkgit:git-help[1]:: - Display help information about Git. - -linkgit:git-instaweb[1]:: - Instantly browse your working repository in gitweb. - -linkgit:git-merge-tree[1]:: - Show three-way merge without touching index. - -linkgit:git-rerere[1]:: - Reuse recorded resolution of conflicted merges. - -linkgit:git-show-branch[1]:: - Show branches and their commits. - -linkgit:git-verify-commit[1]:: - Check the GPG signature of commits. - -linkgit:git-verify-tag[1]:: - Check the GPG signature of tags. - -linkgit:git-whatchanged[1]:: - Show logs with difference each commit introduces. - -linkgit:gitweb[1]:: - Git web interface (web frontend to Git repositories). - diff --git a/cmds-ancillarymanipulators.adoc b/cmds-ancillarymanipulators.adoc new file mode 100644 index 000000000..6fa09e20a --- /dev/null +++ b/cmds-ancillarymanipulators.adoc @@ -0,0 +1,36 @@ +linkgit:git-config[1]:: + Get and set repository or global options. + +linkgit:git-fast-export[1]:: + Git data exporter. + +linkgit:git-fast-import[1]:: + Backend for fast Git data importers. + +linkgit:git-filter-branch[1]:: + Rewrite branches. + +linkgit:git-mergetool[1]:: + Run merge conflict resolution tools to resolve merge conflicts. + +linkgit:git-pack-refs[1]:: + Pack heads and tags for efficient repository access. + +linkgit:git-prune[1]:: + Prune all unreachable objects from the object database. + +linkgit:git-reflog[1]:: + Manage reflog information. + +linkgit:git-refs[1]:: + Low-level access to refs. + +linkgit:git-remote[1]:: + Manage set of tracked repositories. + +linkgit:git-repack[1]:: + Pack unpacked objects in a repository. + +linkgit:git-replace[1]:: + Create, list, delete refs to replace objects. + diff --git a/cmds-ancillarymanipulators.txt b/cmds-ancillarymanipulators.txt deleted file mode 100644 index f3d3f12d3..000000000 --- a/cmds-ancillarymanipulators.txt +++ /dev/null @@ -1,33 +0,0 @@ -linkgit:git-config[1]:: - Get and set repository or global options. - -linkgit:git-fast-export[1]:: - Git data exporter. - -linkgit:git-fast-import[1]:: - Backend for fast Git data importers. - -linkgit:git-filter-branch[1]:: - Rewrite branches. - -linkgit:git-mergetool[1]:: - Run merge conflict resolution tools to resolve merge conflicts. - -linkgit:git-pack-refs[1]:: - Pack heads and tags for efficient repository access. - -linkgit:git-prune[1]:: - Prune all unreachable objects from the object database. - -linkgit:git-reflog[1]:: - Manage reflog information. - -linkgit:git-remote[1]:: - Manage set of tracked repositories. - -linkgit:git-repack[1]:: - Pack unpacked objects in a repository. - -linkgit:git-replace[1]:: - Create, list, delete refs to replace objects. - diff --git a/cmds-developerinterfaces.adoc b/cmds-developerinterfaces.adoc new file mode 100644 index 000000000..810ebe5a1 --- /dev/null +++ b/cmds-developerinterfaces.adoc @@ -0,0 +1,33 @@ +linkgit:gitformat-bundle[5]:: + The bundle file format. + +linkgit:gitformat-chunk[5]:: + Chunk-based file formats. + +linkgit:gitformat-commit-graph[5]:: + Git commit-graph format. + +linkgit:gitformat-index[5]:: + Git index format. + +linkgit:gitformat-pack[5]:: + Git pack format. + +linkgit:gitformat-signature[5]:: + Git cryptographic signature formats. + +linkgit:gitprotocol-capabilities[5]:: + Protocol v0 and v1 capabilities. + +linkgit:gitprotocol-common[5]:: + Things common to various protocols. + +linkgit:gitprotocol-http[5]:: + Git HTTP-based protocols. + +linkgit:gitprotocol-pack[5]:: + How packs are transferred over-the-wire. + +linkgit:gitprotocol-v2[5]:: + Git Wire Protocol, Version 2. + diff --git a/cmds-foreignscminterface.txt b/cmds-foreignscminterface.adoc similarity index 100% rename from cmds-foreignscminterface.txt rename to cmds-foreignscminterface.adoc diff --git a/cmds-guide.adoc b/cmds-guide.adoc new file mode 100644 index 000000000..3c0eeb3dc --- /dev/null +++ b/cmds-guide.adoc @@ -0,0 +1,39 @@ +linkgit:gitcore-tutorial[7]:: + A Git core tutorial for developers. + +linkgit:gitcredentials[7]:: + Providing usernames and passwords to Git. + +linkgit:gitcvs-migration[7]:: + Git for CVS users. + +linkgit:gitdiffcore[7]:: + Tweaking diff output. + +linkgit:giteveryday[7]:: + A useful minimum set of commands for Everyday Git. + +linkgit:gitfaq[7]:: + Frequently asked questions about using Git. + +linkgit:gitglossary[7]:: + A Git Glossary. + +linkgit:gitnamespaces[7]:: + Git namespaces. + +linkgit:gitremote-helpers[7]:: + Helper programs to interact with remote repositories. + +linkgit:gitsubmodules[7]:: + Mounting one repository inside another. + +linkgit:gittutorial[7]:: + A tutorial introduction to Git. + +linkgit:gittutorial-2[7]:: + A tutorial introduction to Git: part two. + +linkgit:gitworkflows[7]:: + An overview of recommended workflows with Git. + diff --git a/cmds-mainporcelain.adoc b/cmds-mainporcelain.adoc new file mode 100644 index 000000000..1374aef01 --- /dev/null +++ b/cmds-mainporcelain.adoc @@ -0,0 +1,135 @@ +linkgit:git-add[1]:: + Add file contents to the index. + +linkgit:git-am[1]:: + Apply a series of patches from a mailbox. + +linkgit:git-archive[1]:: + Create an archive of files from a named tree. + +linkgit:git-backfill[1]:: + Download missing objects in a partial clone. + +linkgit:git-bisect[1]:: + Use binary search to find the commit that introduced a bug. + +linkgit:git-branch[1]:: + List, create, or delete branches. + +linkgit:git-bundle[1]:: + Move objects and refs by archive. + +linkgit:git-checkout[1]:: + Switch branches or restore working tree files. + +linkgit:git-cherry-pick[1]:: + Apply the changes introduced by some existing commits. + +linkgit:git-citool[1]:: + Graphical alternative to git-commit. + +linkgit:git-clean[1]:: + Remove untracked files from the working tree. + +linkgit:git-clone[1]:: + Clone a repository into a new directory. + +linkgit:git-commit[1]:: + Record changes to the repository. + +linkgit:git-describe[1]:: + Give an object a human readable name based on an available ref. + +linkgit:git-diff[1]:: + Show changes between commits, commit and working tree, etc. + +linkgit:git-fetch[1]:: + Download objects and refs from another repository. + +linkgit:git-format-patch[1]:: + Prepare patches for e-mail submission. + +linkgit:git-gc[1]:: + Cleanup unnecessary files and optimize the local repository. + +linkgit:git-grep[1]:: + Print lines matching a pattern. + +linkgit:git-gui[1]:: + A portable graphical interface to Git. + +linkgit:git-init[1]:: + Create an empty Git repository or reinitialize an existing one. + +linkgit:git-log[1]:: + Show commit logs. + +linkgit:git-maintenance[1]:: + Run tasks to optimize Git repository data. + +linkgit:git-merge[1]:: + Join two or more development histories together. + +linkgit:git-mv[1]:: + Move or rename a file, a directory, or a symlink. + +linkgit:git-notes[1]:: + Add or inspect object notes. + +linkgit:git-pull[1]:: + Fetch from and integrate with another repository or a local branch. + +linkgit:git-push[1]:: + Update remote refs along with associated objects. + +linkgit:git-range-diff[1]:: + Compare two commit ranges (e.g. two versions of a branch). + +linkgit:git-rebase[1]:: + Reapply commits on top of another base tip. + +linkgit:git-reset[1]:: + Reset current HEAD to the specified state. + +linkgit:git-restore[1]:: + Restore working tree files. + +linkgit:git-revert[1]:: + Revert some existing commits. + +linkgit:git-rm[1]:: + Remove files from the working tree and from the index. + +linkgit:git-shortlog[1]:: + Summarize 'git log' output. + +linkgit:git-show[1]:: + Show various types of objects. + +linkgit:git-sparse-checkout[1]:: + Reduce your working tree to a subset of tracked files. + +linkgit:git-stash[1]:: + Stash the changes in a dirty working directory away. + +linkgit:git-status[1]:: + Show the working tree status. + +linkgit:git-submodule[1]:: + Initialize, update or inspect submodules. + +linkgit:git-switch[1]:: + Switch branches. + +linkgit:git-tag[1]:: + Create, list, delete or verify tags. + +linkgit:git-worktree[1]:: + Manage multiple working trees. + +linkgit:gitk[1]:: + The Git repository browser. + +linkgit:scalar[1]:: + A tool for managing large Git repositories. + diff --git a/cmds-mainporcelain.txt b/cmds-mainporcelain.txt deleted file mode 100644 index e41a5e12d..000000000 --- a/cmds-mainporcelain.txt +++ /dev/null @@ -1,117 +0,0 @@ -linkgit:git-add[1]:: - Add file contents to the index. - -linkgit:git-am[1]:: - Apply a series of patches from a mailbox. - -linkgit:git-archive[1]:: - Create an archive of files from a named tree. - -linkgit:git-bisect[1]:: - Use binary search to find the commit that introduced a bug. - -linkgit:git-branch[1]:: - List, create, or delete branches. - -linkgit:git-bundle[1]:: - Move objects and refs by archive. - -linkgit:git-checkout[1]:: - Switch branches or restore working tree files. - -linkgit:git-cherry-pick[1]:: - Apply the changes introduced by some existing commits. - -linkgit:git-citool[1]:: - Graphical alternative to git-commit. - -linkgit:git-clean[1]:: - Remove untracked files from the working tree. - -linkgit:git-clone[1]:: - Clone a repository into a new directory. - -linkgit:git-commit[1]:: - Record changes to the repository. - -linkgit:git-describe[1]:: - Give an object a human readable name based on an available ref. - -linkgit:git-diff[1]:: - Show changes between commits, commit and working tree, etc. - -linkgit:git-fetch[1]:: - Download objects and refs from another repository. - -linkgit:git-format-patch[1]:: - Prepare patches for e-mail submission. - -linkgit:git-gc[1]:: - Cleanup unnecessary files and optimize the local repository. - -linkgit:git-grep[1]:: - Print lines matching a pattern. - -linkgit:git-gui[1]:: - A portable graphical interface to Git. - -linkgit:git-init[1]:: - Create an empty Git repository or reinitialize an existing one. - -linkgit:git-log[1]:: - Show commit logs. - -linkgit:git-merge[1]:: - Join two or more development histories together. - -linkgit:git-mv[1]:: - Move or rename a file, a directory, or a symlink. - -linkgit:git-notes[1]:: - Add or inspect object notes. - -linkgit:git-pull[1]:: - Fetch from and integrate with another repository or a local branch. - -linkgit:git-push[1]:: - Update remote refs along with associated objects. - -linkgit:git-range-diff[1]:: - Compare two commit ranges (e.g. two versions of a branch). - -linkgit:git-rebase[1]:: - Reapply commits on top of another base tip. - -linkgit:git-reset[1]:: - Reset current HEAD to the specified state. - -linkgit:git-revert[1]:: - Revert some existing commits. - -linkgit:git-rm[1]:: - Remove files from the working tree and from the index. - -linkgit:git-shortlog[1]:: - Summarize 'git log' output. - -linkgit:git-show[1]:: - Show various types of objects. - -linkgit:git-stash[1]:: - Stash the changes in a dirty working directory away. - -linkgit:git-status[1]:: - Show the working tree status. - -linkgit:git-submodule[1]:: - Initialize, update or inspect submodules. - -linkgit:git-tag[1]:: - Create, list, delete or verify a tag object signed with GPG. - -linkgit:git-worktree[1]:: - Manage multiple working trees. - -linkgit:gitk[1]:: - The Git repository browser. - diff --git a/cmds-plumbinginterrogators.adoc b/cmds-plumbinginterrogators.adoc new file mode 100644 index 000000000..0c53dc017 --- /dev/null +++ b/cmds-plumbinginterrogators.adoc @@ -0,0 +1,72 @@ +linkgit:git-cat-file[1]:: + Provide contents or details of repository objects. + +linkgit:git-cherry[1]:: + Find commits yet to be applied to upstream. + +linkgit:git-diff-files[1]:: + Compares files in the working tree and the index. + +linkgit:git-diff-index[1]:: + Compare a tree to the working tree or index. + +linkgit:git-diff-pairs[1]:: + Compare the content and mode of provided blob pairs. + +linkgit:git-diff-tree[1]:: + Compares the content and mode of blobs found via two tree objects. + +linkgit:git-for-each-ref[1]:: + Output information on each ref. + +linkgit:git-for-each-repo[1]:: + Run a Git command on a list of repositories. + +linkgit:git-get-tar-commit-id[1]:: + Extract commit ID from an archive created using git-archive. + +linkgit:git-last-modified[1]:: + EXPERIMENTAL: Show when files were last modified. + +linkgit:git-ls-files[1]:: + Show information about files in the index and the working tree. + +linkgit:git-ls-remote[1]:: + List references in a remote repository. + +linkgit:git-ls-tree[1]:: + List the contents of a tree object. + +linkgit:git-merge-base[1]:: + Find as good common ancestors as possible for a merge. + +linkgit:git-name-rev[1]:: + Find symbolic names for given revs. + +linkgit:git-pack-redundant[1]:: + Find redundant pack files. + +linkgit:git-repo[1]:: + Retrieve information about the repository. + +linkgit:git-rev-list[1]:: + Lists commit objects in reverse chronological order. + +linkgit:git-rev-parse[1]:: + Pick out and massage parameters. + +linkgit:git-show-index[1]:: + Show packed archive index. + +linkgit:git-show-ref[1]:: + List references in a local repository. + +linkgit:git-unpack-file[1]:: + Creates a temporary file with a blob's contents. + +linkgit:git-var[1]:: + Show a Git logical variable. + +linkgit:git-verify-pack[1]:: + Validate packed Git archive files. + diff --git a/cmds-plumbinginterrogators.txt b/cmds-plumbinginterrogators.txt deleted file mode 100644 index 1b5c8dc06..000000000 --- a/cmds-plumbinginterrogators.txt +++ /dev/null @@ -1,60 +0,0 @@ -linkgit:git-cat-file[1]:: - Provide content or type and size information for repository objects. - -linkgit:git-cherry[1]:: - Find commits yet to be applied to upstream. - -linkgit:git-diff-files[1]:: - Compares files in the working tree and the index. - -linkgit:git-diff-index[1]:: - Compare a tree to the working tree or index. - -linkgit:git-diff-tree[1]:: - Compares the content and mode of blobs found via two tree objects. - -linkgit:git-for-each-ref[1]:: - Output information on each ref. - -linkgit:git-get-tar-commit-id[1]:: - Extract commit ID from an archive created using git-archive. - -linkgit:git-ls-files[1]:: - Show information about files in the index and the working tree. - -linkgit:git-ls-remote[1]:: - List references in a remote repository. - -linkgit:git-ls-tree[1]:: - List the contents of a tree object. - -linkgit:git-merge-base[1]:: - Find as good common ancestors as possible for a merge. - -linkgit:git-name-rev[1]:: - Find symbolic names for given revs. - -linkgit:git-pack-redundant[1]:: - Find redundant pack files. - -linkgit:git-rev-list[1]:: - Lists commit objects in reverse chronological order. - -linkgit:git-rev-parse[1]:: - Pick out and massage parameters. - -linkgit:git-show-index[1]:: - Show packed archive index. - -linkgit:git-show-ref[1]:: - List references in a local repository. - -linkgit:git-unpack-file[1]:: - Creates a temporary file with a blob's contents. - -linkgit:git-var[1]:: - Show a Git logical variable. - -linkgit:git-verify-pack[1]:: - Validate packed Git archive files. - diff --git a/cmds-plumbingmanipulators.adoc b/cmds-plumbingmanipulators.adoc new file mode 100644 index 000000000..6ea8c605c --- /dev/null +++ b/cmds-plumbingmanipulators.adoc @@ -0,0 +1,60 @@ +linkgit:git-apply[1]:: + Apply a patch to files and/or to the index. + +linkgit:git-checkout-index[1]:: + Copy files from the index to the working tree. + +linkgit:git-commit-graph[1]:: + Write and verify Git commit-graph files. + +linkgit:git-commit-tree[1]:: + Create a new commit object. + +linkgit:git-hash-object[1]:: + Compute object ID and optionally create an object from a file. + +linkgit:git-index-pack[1]:: + Build pack index file for an existing packed archive. + +linkgit:git-merge-file[1]:: + Run a three-way file merge. + +linkgit:git-merge-index[1]:: + Run a merge for files needing merging. + +linkgit:git-mktag[1]:: + Creates a tag object with extra validation. + +linkgit:git-mktree[1]:: + Build a tree-object from ls-tree formatted text. + +linkgit:git-multi-pack-index[1]:: + Write and verify multi-pack-indexes. + +linkgit:git-pack-objects[1]:: + Create a packed archive of objects. + +linkgit:git-prune-packed[1]:: + Remove extra objects that are already in pack files. + +linkgit:git-read-tree[1]:: + Reads tree information into the index. + +linkgit:git-replay[1]:: + EXPERIMENTAL: Replay commits on a new base, works with bare repos too. + +linkgit:git-symbolic-ref[1]:: + Read, modify and delete symbolic refs. + +linkgit:git-unpack-objects[1]:: + Unpack objects from a packed archive. + +linkgit:git-update-index[1]:: + Register file contents in the working tree to the index. + +linkgit:git-update-ref[1]:: + Update the object name stored in a ref safely. + +linkgit:git-write-tree[1]:: + Create a tree object from the current index. + diff --git a/cmds-plumbingmanipulators.txt b/cmds-plumbingmanipulators.txt deleted file mode 100644 index b6840534d..000000000 --- a/cmds-plumbingmanipulators.txt +++ /dev/null @@ -1,57 +0,0 @@ -linkgit:git-apply[1]:: - Apply a patch to files and/or to the index. - -linkgit:git-checkout-index[1]:: - Copy files from the index to the working tree. - -linkgit:git-commit-graph[1]:: - Write and verify Git commit-graph files. - -linkgit:git-commit-tree[1]:: - Create a new commit object. - -linkgit:git-hash-object[1]:: - Compute object ID and optionally creates a blob from a file. - -linkgit:git-index-pack[1]:: - Build pack index file for an existing packed archive. - -linkgit:git-merge-file[1]:: - Run a three-way file merge. - -linkgit:git-merge-index[1]:: - Run a merge for files needing merging. - -linkgit:git-mktag[1]:: - Creates a tag object. - -linkgit:git-mktree[1]:: - Build a tree-object from ls-tree formatted text. - -linkgit:git-multi-pack-index[1]:: - Write and verify multi-pack-indexes. - -linkgit:git-pack-objects[1]:: - Create a packed archive of objects. - -linkgit:git-prune-packed[1]:: - Remove extra objects that are already in pack files. - -linkgit:git-read-tree[1]:: - Reads tree information into the index. - -linkgit:git-symbolic-ref[1]:: - Read, modify and delete symbolic refs. - -linkgit:git-unpack-objects[1]:: - Unpack objects from a packed archive. - -linkgit:git-update-index[1]:: - Register file contents in the working tree to the index. - -linkgit:git-update-ref[1]:: - Update the object name stored in a ref safely. - -linkgit:git-write-tree[1]:: - Create a tree object from the current index. - diff --git a/cmds-purehelpers.adoc b/cmds-purehelpers.adoc new file mode 100644 index 000000000..259298821 --- /dev/null +++ b/cmds-purehelpers.adoc @@ -0,0 +1,54 @@ +linkgit:git-check-attr[1]:: + Display gitattributes information. + +linkgit:git-check-ignore[1]:: + Debug gitignore / exclude files. + +linkgit:git-check-mailmap[1]:: + Show canonical names and email addresses of contacts. + +linkgit:git-check-ref-format[1]:: + Ensures that a reference name is well formed. + +linkgit:git-column[1]:: + Display data in columns. + +linkgit:git-credential[1]:: + Retrieve and store user credentials. + +linkgit:git-credential-cache[1]:: + Helper to temporarily store passwords in memory. + +linkgit:git-credential-store[1]:: + Helper to store credentials on disk. + +linkgit:git-fmt-merge-msg[1]:: + Produce a merge commit message. + +linkgit:git-hook[1]:: + Run git hooks. + +linkgit:git-interpret-trailers[1]:: + Add or parse structured information in commit messages. + +linkgit:git-mailinfo[1]:: + Extracts patch and authorship from a single e-mail message. + +linkgit:git-mailsplit[1]:: + Simple UNIX mbox splitter program. + +linkgit:git-merge-one-file[1]:: + The standard helper program to use with git-merge-index. + +linkgit:git-patch-id[1]:: + Compute unique ID for a patch. + +linkgit:git-sh-i18n[1]:: + Git's i18n setup code for shell scripts. + +linkgit:git-sh-setup[1]:: + Common Git shell script setup code. + +linkgit:git-stripspace[1]:: + Remove unnecessary whitespace. + diff --git a/cmds-purehelpers.txt b/cmds-purehelpers.txt deleted file mode 100644 index 080421d3b..000000000 --- a/cmds-purehelpers.txt +++ /dev/null @@ -1,51 +0,0 @@ -linkgit:git-check-attr[1]:: - Display gitattributes information. - -linkgit:git-check-ignore[1]:: - Debug gitignore / exclude files. - -linkgit:git-check-mailmap[1]:: - Show canonical names and email addresses of contacts. - -linkgit:git-check-ref-format[1]:: - Ensures that a reference name is well formed. - -linkgit:git-column[1]:: - Display data in columns. - -linkgit:git-credential[1]:: - Retrieve and store user credentials. - -linkgit:git-credential-cache[1]:: - Helper to temporarily store passwords in memory. - -linkgit:git-credential-store[1]:: - Helper to store credentials on disk. - -linkgit:git-fmt-merge-msg[1]:: - Produce a merge commit message. - -linkgit:git-interpret-trailers[1]:: - add or parse structured information in commit messages. - -linkgit:git-mailinfo[1]:: - Extracts patch and authorship from a single e-mail message. - -linkgit:git-mailsplit[1]:: - Simple UNIX mbox splitter program. - -linkgit:git-merge-one-file[1]:: - The standard helper program to use with git-merge-index. - -linkgit:git-patch-id[1]:: - Compute unique ID for a patch. - -linkgit:git-sh-i18n[1]:: - Git's i18n setup code for shell scripts. - -linkgit:git-sh-setup[1]:: - Common Git shell script setup code. - -linkgit:git-stripspace[1]:: - Remove unnecessary whitespace. - diff --git a/cmds-synchelpers.adoc b/cmds-synchelpers.adoc new file mode 100644 index 000000000..253c5d352 --- /dev/null +++ b/cmds-synchelpers.adoc @@ -0,0 +1,18 @@ +linkgit:git-http-fetch[1]:: + Download from a remote Git repository via HTTP. + +linkgit:git-http-push[1]:: + Push objects over HTTP/DAV to another repository. + +linkgit:git-receive-pack[1]:: + Receive what is pushed into the repository. + +linkgit:git-shell[1]:: + Restricted login shell for Git-only SSH access. + +linkgit:git-upload-archive[1]:: + Send archive back to git-archive. + +linkgit:git-upload-pack[1]:: + Send objects packed back to git-fetch-pack. + diff --git a/cmds-synchelpers.txt b/cmds-synchelpers.txt deleted file mode 100644 index 6ff96cea1..000000000 --- a/cmds-synchelpers.txt +++ /dev/null @@ -1,21 +0,0 @@ -linkgit:git-http-fetch[1]:: - Download from a remote Git repository via HTTP. - -linkgit:git-http-push[1]:: - Push objects over HTTP/DAV to another repository. - -linkgit:git-parse-remote[1]:: - Routines to help parsing remote repository access parameters. - -linkgit:git-receive-pack[1]:: - Receive what is pushed into the repository. - -linkgit:git-shell[1]:: - Restricted login shell for Git-only SSH access. - -linkgit:git-upload-archive[1]:: - Send archive back to git-archive. - -linkgit:git-upload-pack[1]:: - Send objects packed back to git-fetch-pack. - diff --git a/cmds-synchingrepositories.txt b/cmds-synchingrepositories.adoc similarity index 100% rename from cmds-synchingrepositories.txt rename to cmds-synchingrepositories.adoc diff --git a/cmds-userinterfaces.adoc b/cmds-userinterfaces.adoc new file mode 100644 index 000000000..dae805335 --- /dev/null +++ b/cmds-userinterfaces.adoc @@ -0,0 +1,24 @@ +linkgit:gitattributes[5]:: + Defining attributes per path. + +linkgit:gitcli[7]:: + Git command-line interface and conventions. + +linkgit:githooks[5]:: + Hooks used by Git. + +linkgit:gitignore[5]:: + Specifies intentionally untracked files to ignore. + +linkgit:gitmailmap[5]:: + Map author/committer names and/or E-Mail addresses. + +linkgit:gitmodules[5]:: + Defining submodule properties. + +linkgit:gitrepository-layout[5]:: + Git Repository Layout. + +linkgit:gitrevisions[7]:: + Specifying revisions and ranges for Git. + diff --git a/config.adoc b/config.adoc new file mode 100644 index 000000000..62eebe7c5 --- /dev/null +++ b/config.adoc @@ -0,0 +1,560 @@ +CONFIGURATION FILE +------------------ + +The Git configuration file contains a number of variables that affect +the Git commands' behavior. The files `.git/config` and optionally +`config.worktree` (see the "CONFIGURATION FILE" section of +linkgit:git-worktree[1]) in each repository are used to store the +configuration for that repository, and `$HOME/.gitconfig` is used to +store a per-user configuration as fallback values for the `.git/config` +file. The file `/etc/gitconfig` can be used to store a system-wide +default configuration. + +The configuration variables are used by both the Git plumbing +and the porcelain commands. The variables are divided into sections, wherein +the fully qualified variable name of 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, allow only alphanumeric +characters and `-`, and must start with an alphabetic character. Some +variables may appear multiple times; we say then that the variable is +multivalued. + +Syntax +~~~~~~ + +The syntax is fairly flexible and permissive. Whitespace characters, +which in this context are the space character (SP) and the horizontal +tabulation (HT), are mostly ignored. The '#' and ';' characters begin +comments to the end of line. Blank lines are ignored. + +The file consists of sections and variables. A section begins with +the name of the section in square brackets and continues until the next +section begins. Section names are case-insensitive. Only alphanumeric +characters, `-` and `.` are allowed in section names. Each variable +must belong to some section, which means that there must be a section +header before the first setting of a variable. + +Sections can be further divided into subsections. To begin a subsection +put its name in double quotes, separated by space from the section name, +in the section header, like in the example below: + +-------- + [section "subsection"] + +-------- + +Subsection names are case sensitive and can contain any characters except +newline and the null byte. Doublequote `"` and backslash can be included +by escaping them as `\"` and `\\`, respectively. Backslashes preceding +other characters are dropped when reading; for example, `\t` is read as +`t` and `\0` is read as `0`. Section headers cannot span multiple lines. +Variables may belong directly to a section or to a given subsection. You +can have `[section]` if you have `[section "subsection"]`, but you don't +need to. + +There is also a deprecated `[section.subsection]` syntax. With this +syntax, the subsection name is converted to lower-case and is also +compared case sensitively. These subsection names follow the same +restrictions as section names. + +All the other lines (and the remainder of the line after the section +header) are recognized as setting variables, in the form +'name = value' (or just 'name', which is a short-hand to say that +the variable is the boolean "true"). +The variable names are case-insensitive, allow only alphanumeric characters +and `-`, and must start with an alphabetic character. + +Whitespace characters surrounding `name`, `=` and `value` are discarded. +Internal whitespace characters within 'value' are retained verbatim. +Comments starting with either `#` or `;` and extending to the end of line +are discarded. A line that defines a value can be continued to the next +line by ending it with a backslash (`\`); the backslash and the end-of-line +characters are discarded. + +If `value` needs to contain leading or trailing whitespace characters, +it must be enclosed in double quotation marks (`"`). Inside double quotation +marks, double quote (`"`) and backslash (`\`) characters must be escaped: +use `\"` for `"` and `\\` for `\`. + +The following escape sequences (beside `\"` and `\\`) are recognized: +`\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB) +and `\b` for backspace (BS). Other char escape sequences (including octal +escape sequences) are invalid. + + +Includes +~~~~~~~~ + +The `include` and `includeIf` sections allow you to include config +directives from another source. These sections behave identically to +each other with the exception that `includeIf` sections may be ignored +if their condition does not evaluate to true; see "Conditional includes" +below. + +You can include a config file from another by setting the special +`include.path` (or `includeIf.*.path`) variable to the name of the file +to be included. The variable takes a pathname as its value, and is +subject to tilde expansion. These variables can be given multiple times. + +The contents of the included file are inserted immediately, as if they +had been found at the location of the include directive. If the value of the +variable is a relative path, the path is considered to +be relative to the configuration file in which the include directive +was found. See below for examples. + +Conditional includes +~~~~~~~~~~~~~~~~~~~~ + +You can conditionally include a config file from another by setting an +`includeIf..path` variable to the name of the file to be +included. + +The condition starts with a keyword followed by a colon and some data +whose format and meaning depends on the keyword. Supported keywords +are: + +`gitdir`:: + The data that follows the keyword `gitdir` and a colon is used as a glob + pattern. If the location of the .git directory matches the + pattern, the include condition is met. ++ +The .git location may be auto-discovered, or come from `$GIT_DIR` +environment variable. If the repository is auto-discovered via a .git +file (e.g. from submodules, or a linked worktree), the .git location +would be the final location where the .git directory is, not where the +.git file is. ++ +The pattern can contain standard globbing wildcards and two additional +ones, `**/` and `/**`, that can match multiple path components. Please +refer to linkgit:gitignore[5] for details. For convenience: + + * If the pattern starts with `~/`, `~` will be substituted with the + content of the environment variable `HOME`. + + * If the pattern starts with `./`, it is replaced with the directory + containing the current config file. + + * If the pattern does not start with either `~/`, `./` or `/`, `**/` + will be automatically prepended. For example, the pattern `foo/bar` + becomes `**/foo/bar` and would match `/any/path/to/foo/bar`. + + * If the pattern ends with `/`, `**` will be automatically added. For + example, the pattern `foo/` becomes `foo/**`. In other words, it + matches "foo" and everything inside, recursively. + +`gitdir/i`:: + This is the same as `gitdir` except that matching is done + case-insensitively (e.g. on case-insensitive file systems) + +`onbranch`:: + The data that follows the keyword `onbranch` and a colon is taken to be a + pattern with standard globbing wildcards and two additional + ones, `**/` and `/**`, that can match multiple path components. + If we are in a worktree where the name of the branch that is + currently checked out matches the pattern, the include condition + is met. ++ +If the pattern ends with `/`, `**` will be automatically added. For +example, the pattern `foo/` becomes `foo/**`. In other words, it matches +all branches that begin with `foo/`. This is useful if your branches are +organized hierarchically and you would like to apply a configuration to +all the branches in that hierarchy. + +`hasconfig:remote.*.url`:: + The data that follows this keyword and a colon is taken to + be a pattern with standard globbing wildcards and two + additional ones, `**/` and `/**`, that can match multiple + components. The first time this keyword is seen, the rest of + the config files will be scanned for remote URLs (without + applying any values). If there exists at least one remote URL + that matches this pattern, the include condition is met. ++ +Files included by this option (directly or indirectly) are not allowed +to contain remote URLs. ++ +Note that unlike other includeIf conditions, resolving this condition +relies on information that is not yet known at the point of reading the +condition. A typical use case is this option being present as a +system-level or global-level config, and the remote URL being in a +local-level config; hence the need to scan ahead when resolving this +condition. In order to avoid the chicken-and-egg problem in which +potentially-included files can affect whether such files are potentially +included, Git breaks the cycle by prohibiting these files from affecting +the resolution of these conditions (thus, prohibiting them from +declaring remote URLs). ++ +As for the naming of this keyword, it is for forwards compatibility with +a naming scheme that supports more variable-based include conditions, +but currently Git only supports the exact keyword described above. + +A few more notes on matching via `gitdir` and `gitdir/i`: + + * Symlinks in `$GIT_DIR` are not resolved before matching. + + * Both the symlink & realpath versions of paths will be matched + outside of `$GIT_DIR`. E.g. if ~/git is a symlink to + /mnt/storage/git, both `gitdir:~/git` and `gitdir:/mnt/storage/git` + will match. ++ +This was not the case in the initial release of this feature in +v2.13.0, which only matched the realpath version. Configuration that +wants to be compatible with the initial release of this feature needs +to either specify only the realpath version, or both versions. + + * Note that "../" is not special and will match literally, which is + unlikely what you want. + +Example +~~~~~~~ + +---- +# Core variables +[core] + ; Don't trust file modes + filemode = false + +# Our diff algorithm +[diff] + external = /usr/local/bin/diff-wrapper + renames = true + +[branch "devel"] + remote = origin + merge = refs/heads/devel + +# Proxy settings +[core] + gitProxy="ssh" for "kernel.org" + gitProxy=default-proxy ; for the rest + +[include] + path = /path/to/foo.inc ; include by absolute path + path = foo.inc ; find "foo.inc" relative to the current file + path = ~/foo.inc ; find "foo.inc" in your `$HOME` directory + +; include if $GIT_DIR is /path/to/foo/.git +[includeIf "gitdir:/path/to/foo/.git"] + path = /path/to/foo.inc + +; include for all repositories inside /path/to/group +[includeIf "gitdir:/path/to/group/"] + path = /path/to/foo.inc + +; include for all repositories inside $HOME/to/group +[includeIf "gitdir:~/to/group/"] + path = /path/to/foo.inc + +; relative paths are always relative to the including +; file (if the condition is true); their location is not +; affected by the condition +[includeIf "gitdir:/path/to/group/"] + path = foo.inc + +; include only if we are in a worktree where foo-branch is +; currently checked out +[includeIf "onbranch:foo-branch"] + path = foo.inc + +; include only if a remote with the given URL exists (note +; that such a URL may be provided later in a file or in a +; file read after this file is read, as seen in this example) +[includeIf "hasconfig:remote.*.url:https://example.com/**"] + path = foo.inc +[remote "origin"] + url = https://example.com/git +---- + +Values +~~~~~~ + +Values of many variables are treated as a simple string, but there +are variables that take values of specific types and there are rules +as to how to spell them. + +boolean:: + + When a variable is said to take a boolean value, many + synonyms are accepted for 'true' and 'false'; these are all + case-insensitive. + + true;; Boolean true literals are `yes`, `on`, `true`, + and `1`. Also, a variable defined without `= ` + is taken as true. + + false;; Boolean false literals are `no`, `off`, `false`, + `0` and the empty string. ++ +When converting a value to its canonical form using the `--type=bool` type +specifier, 'git config' will ensure that the output is "true" or +"false" (spelled in lowercase). + +integer:: + The value for many variables that specify various sizes can + be suffixed with `k`, `M`,... to mean "scale the number by + 1024", "by 1024x1024", etc. + +color:: + The value for a variable that takes a color is a list of + colors (at most two, one for foreground and one for background) + and attributes (as many as you want), separated by spaces. ++ +The basic colors accepted are `normal`, `black`, `red`, `green`, +`yellow`, `blue`, `magenta`, `cyan`, `white` and `default`. The first +color given is the foreground; the second is the background. All the +basic colors except `normal` and `default` have a bright variant that can +be specified by prefixing the color with `bright`, like `brightred`. ++ +The color `normal` makes no change to the color. It is the same as an +empty string, but can be used as the foreground color when specifying a +background color alone (for example, "normal red"). ++ +The color `default` explicitly resets the color to the terminal default, +for example to specify a cleared background. Although it varies between +terminals, this is usually not the same as setting to "white black". ++ +Colors may also be given as numbers between 0 and 255; these use ANSI +256-color mode (but note that not all terminals may support this). If +your terminal supports it, you may also specify 24-bit RGB values as +hex, like `#ff0ab3`, or 12-bit RGB values like `#f1b`, which is +equivalent to the 24-bit color `#ff11bb`. ++ +The accepted attributes are `bold`, `dim`, `ul`, `blink`, `reverse`, +`italic`, and `strike` (for crossed-out or "strikethrough" letters). +The position of any attributes with respect to the colors +(before, after, or in between), doesn't matter. Specific attributes may +be turned off by prefixing them with `no` or `no-` (e.g., `noreverse`, +`no-ul`, etc). ++ +The pseudo-attribute `reset` resets all colors and attributes before +applying the specified coloring. For example, `reset green` will result +in a green foreground and default background without any active +attributes. ++ +An empty color string produces no color effect at all. This can be used +to avoid coloring specific elements without disabling color entirely. ++ +For git's pre-defined color slots, the attributes are meant to be reset +at the beginning of each item in the colored output. So setting +`color.decorate.branch` to `black` will paint that branch name in a +plain `black`, even if the previous thing on the same output line (e.g. +opening parenthesis before the list of branch names in `log --decorate` +output) is set to be painted with `bold` or some other attribute. +However, custom log formats may do more complicated and layered +coloring, and the negated forms may be useful there. + +pathname:: + A variable that takes a pathname value can be given a + string that begins with "`~/`" or "`~user/`", and the usual + tilde expansion happens to such a string: `~/` + is expanded to the value of `$HOME`, and `~user/` to the + specified user's home directory. ++ +If a path starts with `%(prefix)/`, the remainder is interpreted as a +path relative to Git's "runtime prefix", i.e. relative to the location +where Git itself was installed. For example, `%(prefix)/bin/` refers to +the directory in which the Git executable itself lives. If Git was +compiled without runtime prefix support, the compiled-in prefix will be +substituted instead. In the unlikely event that a literal path needs to +be specified that should _not_ be expanded, it needs to be prefixed by +`./`, like so: `./%(prefix)/bin`. ++ +If prefixed with `:(optional)`, the configuration variable is treated +as if it does not exist, if the named path does not exist. + +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. + +Other git-related tools may and do use their own variables. When +inventing new variables for use in your own tool, make sure their +names do not conflict with those that are used by Git itself and +other popular tools, and describe them in your documentation. + +include::config/add.adoc[] + +include::config/advice.adoc[] + +include::config/alias.adoc[] + +include::config/am.adoc[] + +include::config/apply.adoc[] + +include::config/attr.adoc[] + +include::config/bitmap-pseudo-merge.adoc[] + +include::config/blame.adoc[] + +include::config/branch.adoc[] + +include::config/browser.adoc[] + +include::config/bundle.adoc[] + +include::config/checkout.adoc[] + +include::config/clean.adoc[] + +include::config/clone.adoc[] + +include::config/color.adoc[] + +include::config/column.adoc[] + +include::config/commit.adoc[] + +include::config/commitgraph.adoc[] + +include::config/completion.adoc[] + +include::config/core.adoc[] + +include::config/credential.adoc[] + +include::config/diff.adoc[] + +include::config/difftool.adoc[] + +include::config/extensions.adoc[] + +include::config/fastimport.adoc[] + +include::config/feature.adoc[] + +include::config/fetch.adoc[] + +include::config/filter.adoc[] + +include::config/format.adoc[] + +include::config/fsck.adoc[] + +include::config/fsmonitor--daemon.adoc[] + +include::config/gc.adoc[] + +include::config/gitcvs.adoc[] + +include::config/gitweb.adoc[] + +include::config/gpg.adoc[] + +include::config/grep.adoc[] + +include::config/gui.adoc[] + +include::config/guitool.adoc[] + +include::config/help.adoc[] + +include::config/http.adoc[] + +include::config/i18n.adoc[] + +include::config/imap.adoc[] + +include::config/includeif.adoc[] + +include::config/index.adoc[] + +include::config/init.adoc[] + +include::config/instaweb.adoc[] + +include::config/interactive.adoc[] + +include::config/log.adoc[] + +include::config/lsrefs.adoc[] + +include::config/mailinfo.adoc[] + +include::config/mailmap.adoc[] + +include::config/maintenance.adoc[] + +include::config/man.adoc[] + +include::config/merge.adoc[] + +include::config/mergetool.adoc[] + +include::config/notes.adoc[] + +include::config/pack.adoc[] + +include::config/pager.adoc[] + +include::config/pretty.adoc[] + +include::config/promisor.adoc[] + +include::config/protocol.adoc[] + +include::config/pull.adoc[] + +include::config/push.adoc[] + +include::config/rebase.adoc[] + +include::config/receive.adoc[] + +include::config/reftable.adoc[] + +include::config/remote.adoc[] + +include::config/remotes.adoc[] + +include::config/repack.adoc[] + +include::config/rerere.adoc[] + +include::config/revert.adoc[] + +include::config/safe.adoc[] + +include::config/sendemail.adoc[] + +include::config/sequencer.adoc[] + +include::config/showbranch.adoc[] + +include::config/sparse.adoc[] + +include::config/splitindex.adoc[] + +include::config/ssh.adoc[] + +include::config/stash.adoc[] + +include::config/status.adoc[] + +include::config/submodule.adoc[] + +include::config/tag.adoc[] + +include::config/tar.adoc[] + +include::config/trace2.adoc[] + +include::config/trailer.adoc[] + +include::config/transfer.adoc[] + +include::config/uploadarchive.adoc[] + +include::config/uploadpack.adoc[] + +include::config/url.adoc[] + +include::config/user.adoc[] + +include::config/versionsort.adoc[] + +include::config/web.adoc[] + +include::config/worktree.adoc[] diff --git a/config.txt b/config.txt deleted file mode 100644 index d87846faa..000000000 --- a/config.txt +++ /dev/null @@ -1,439 +0,0 @@ -CONFIGURATION FILE ------------------- - -The Git configuration file contains a number of variables that affect -the Git commands' behavior. The files `.git/config` and optionally -`config.worktree` (see `extensions.worktreeConfig` below) in each -repository are used to store the configuration for that repository, and -`$HOME/.gitconfig` is used to store a per-user configuration as -fallback values for the `.git/config` file. The file `/etc/gitconfig` -can be used to store a system-wide default configuration. - -The configuration variables are used by both the Git plumbing -and the porcelains. The variables are divided into sections, wherein -the fully qualified variable name of 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, allow only alphanumeric -characters and `-`, and must start with an alphabetic character. Some -variables may appear multiple times; we say then that the variable is -multivalued. - -Syntax -~~~~~~ - -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. - -The file consists of sections and variables. A section begins with -the name of the section in square brackets and continues until the next -section begins. Section names are case-insensitive. Only alphanumeric -characters, `-` and `.` are allowed in section names. Each variable -must belong to some section, which means that there must be a section -header before the first setting of a variable. - -Sections can be further divided into subsections. To begin a subsection -put its name in double quotes, separated by space from the section name, -in the section header, like in the example below: - --------- - [section "subsection"] - --------- - -Subsection names are case sensitive and can contain any characters except -newline and the null byte. Doublequote `"` and backslash can be included -by escaping them as `\"` and `\\`, respectively. Backslashes preceding -other characters are dropped when reading; for example, `\t` is read as -`t` and `\0` is read as `0` Section headers cannot span multiple lines. -Variables may belong directly to a section or to a given subsection. You -can have `[section]` if you have `[section "subsection"]`, but you don't -need to. - -There is also a deprecated `[section.subsection]` syntax. With this -syntax, the subsection name is converted to lower-case and is also -compared case sensitively. These subsection names follow the same -restrictions as section names. - -All the other lines (and the remainder of the line after the section -header) are recognized as setting variables, in the form -'name = value' (or just 'name', which is a short-hand to say that -the variable is the boolean "true"). -The variable names are case-insensitive, allow only alphanumeric characters -and `-`, and must start with an alphabetic character. - -A line that defines a value can be continued to the next line by -ending it with a `\`; the backquote and the end-of-line are -stripped. Leading whitespaces after 'name =', the remainder of the -line after the first comment character '#' or ';', and trailing -whitespaces of the line are discarded unless they are enclosed in -double quotes. Internal whitespaces within the value are retained -verbatim. - -Inside double quotes, double quote `"` and backslash `\` characters -must be escaped: use `\"` for `"` and `\\` for `\`. - -The following escape sequences (beside `\"` and `\\`) are recognized: -`\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB) -and `\b` for backspace (BS). Other char escape sequences (including octal -escape sequences) are invalid. - - -Includes -~~~~~~~~ - -The `include` and `includeIf` sections allow you to include config -directives from another source. These sections behave identically to -each other with the exception that `includeIf` sections may be ignored -if their condition does not evaluate to true; see "Conditional includes" -below. - -You can include a config file from another by setting the special -`include.path` (or `includeIf.*.path`) variable to the name of the file -to be included. The variable takes a pathname as its value, and is -subject to tilde expansion. These variables can be given multiple times. - -The contents of the included file are inserted immediately, as if they -had been found at the location of the include directive. If the value of the -variable is a relative path, the path is considered to -be relative to the configuration file in which the include directive -was found. See below for examples. - -Conditional includes -~~~~~~~~~~~~~~~~~~~~ - -You can include a config file from another conditionally by setting a -`includeIf..path` variable to the name of the file to be -included. - -The condition starts with a keyword followed by a colon and some data -whose format and meaning depends on the keyword. Supported keywords -are: - -`gitdir`:: - - The data that follows the keyword `gitdir:` is used as a glob - pattern. If the location of the .git directory matches the - pattern, the include condition is met. -+ -The .git location may be auto-discovered, or come from `$GIT_DIR` -environment variable. If the repository is auto discovered via a .git -file (e.g. from submodules, or a linked worktree), the .git location -would be the final location where the .git directory is, not where the -.git file is. -+ -The pattern can contain standard globbing wildcards and two additional -ones, `**/` and `/**`, that can match multiple path components. Please -refer to linkgit:gitignore[5] for details. For convenience: - - * If the pattern starts with `~/`, `~` will be substituted with the - content of the environment variable `HOME`. - - * If the pattern starts with `./`, it is replaced with the directory - containing the current config file. - - * If the pattern does not start with either `~/`, `./` or `/`, `**/` - will be automatically prepended. For example, the pattern `foo/bar` - becomes `**/foo/bar` and would match `/any/path/to/foo/bar`. - - * If the pattern ends with `/`, `**` will be automatically added. For - example, the pattern `foo/` becomes `foo/**`. In other words, it - matches "foo" and everything inside, recursively. - -`gitdir/i`:: - This is the same as `gitdir` except that matching is done - case-insensitively (e.g. on case-insensitive file sytems) - -A few more notes on matching via `gitdir` and `gitdir/i`: - - * Symlinks in `$GIT_DIR` are not resolved before matching. - - * Both the symlink & realpath versions of paths will be matched - outside of `$GIT_DIR`. E.g. if ~/git is a symlink to - /mnt/storage/git, both `gitdir:~/git` and `gitdir:/mnt/storage/git` - will match. -+ -This was not the case in the initial release of this feature in -v2.13.0, which only matched the realpath version. Configuration that -wants to be compatible with the initial release of this feature needs -to either specify only the realpath version, or both versions. - - * Note that "../" is not special and will match literally, which is - unlikely what you want. - -Example -~~~~~~~ - - # Core variables - [core] - ; Don't trust file modes - filemode = false - - # Our diff algorithm - [diff] - external = /usr/local/bin/diff-wrapper - renames = true - - [branch "devel"] - remote = origin - merge = refs/heads/devel - - # Proxy settings - [core] - gitProxy="ssh" for "kernel.org" - gitProxy=default-proxy ; for the rest - - [include] - path = /path/to/foo.inc ; include by absolute path - path = foo.inc ; find "foo.inc" relative to the current file - path = ~/foo.inc ; find "foo.inc" in your `$HOME` directory - - ; include if $GIT_DIR is /path/to/foo/.git - [includeIf "gitdir:/path/to/foo/.git"] - path = /path/to/foo.inc - - ; include for all repositories inside /path/to/group - [includeIf "gitdir:/path/to/group/"] - path = /path/to/foo.inc - - ; include for all repositories inside $HOME/to/group - [includeIf "gitdir:~/to/group/"] - path = /path/to/foo.inc - - ; relative paths are always relative to the including - ; file (if the condition is true); their location is not - ; affected by the condition - [includeIf "gitdir:/path/to/group/"] - path = foo.inc - -Values -~~~~~~ - -Values of many variables are treated as a simple string, but there -are variables that take values of specific types and there are rules -as to how to spell them. - -boolean:: - - When a variable is said to take a boolean value, many - synonyms are accepted for 'true' and 'false'; these are all - case-insensitive. - - true;; Boolean true literals are `yes`, `on`, `true`, - and `1`. Also, a variable defined without `= ` - is taken as true. - - false;; Boolean false literals are `no`, `off`, `false`, - `0` and the empty string. -+ -When converting a value to its canonical form using the `--type=bool` type -specifier, 'git config' will ensure that the output is "true" or -"false" (spelled in lowercase). - -integer:: - The value for many variables that specify various sizes can - be suffixed with `k`, `M`,... to mean "scale the number by - 1024", "by 1024x1024", etc. - -color:: - The value for a variable that takes a color is a list of - colors (at most two, one for foreground and one for background) - and attributes (as many as you want), separated by spaces. -+ -The basic colors accepted are `normal`, `black`, `red`, `green`, `yellow`, -`blue`, `magenta`, `cyan` and `white`. The first color given is the -foreground; the second is the background. -+ -Colors may also be given as numbers between 0 and 255; these use ANSI -256-color mode (but note that not all terminals may support this). If -your terminal supports it, you may also specify 24-bit RGB values as -hex, like `#ff0ab3`. -+ -The accepted attributes are `bold`, `dim`, `ul`, `blink`, `reverse`, -`italic`, and `strike` (for crossed-out or "strikethrough" letters). -The position of any attributes with respect to the colors -(before, after, or in between), doesn't matter. Specific attributes may -be turned off by prefixing them with `no` or `no-` (e.g., `noreverse`, -`no-ul`, etc). -+ -An empty color string produces no color effect at all. This can be used -to avoid coloring specific elements without disabling color entirely. -+ -For git's pre-defined color slots, the attributes are meant to be reset -at the beginning of each item in the colored output. So setting -`color.decorate.branch` to `black` will paint that branch name in a -plain `black`, even if the previous thing on the same output line (e.g. -opening parenthesis before the list of branch names in `log --decorate` -output) is set to be painted with `bold` or some other attribute. -However, custom log formats may do more complicated and layered -coloring, and the negated forms may be useful there. - -pathname:: - A variable that takes a pathname value can be given a - string that begins with "`~/`" or "`~user/`", and the usual - tilde expansion happens to such a string: `~/` - is expanded to the value of `$HOME`, and `~user/` to the - specified user's home directory. - - -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. - -Other git-related tools may and do use their own variables. When -inventing new variables for use in your own tool, make sure their -names do not conflict with those that are used by Git itself and -other popular tools, and describe them in your documentation. - -include::config/advice.txt[] - -include::config/core.txt[] - -include::config/add.txt[] - -include::config/alias.txt[] - -include::config/am.txt[] - -include::config/apply.txt[] - -include::config/blame.txt[] - -include::config/branch.txt[] - -include::config/browser.txt[] - -include::config/checkout.txt[] - -include::config/clean.txt[] - -include::config/color.txt[] - -include::config/column.txt[] - -include::config/commit.txt[] - -include::config/credential.txt[] - -include::config/completion.txt[] - -include::config/diff.txt[] - -include::config/difftool.txt[] - -include::config/fastimport.txt[] - -include::config/fetch.txt[] - -include::config/format.txt[] - -include::config/filter.txt[] - -include::config/fsck.txt[] - -include::config/gc.txt[] - -include::config/gitcvs.txt[] - -include::config/gitweb.txt[] - -include::config/grep.txt[] - -include::config/gpg.txt[] - -include::config/gui.txt[] - -include::config/guitool.txt[] - -include::config/help.txt[] - -include::config/http.txt[] - -include::config/i18n.txt[] - -include::config/imap.txt[] - -include::config/index.txt[] - -include::config/init.txt[] - -include::config/instaweb.txt[] - -include::config/interactive.txt[] - -include::config/log.txt[] - -include::config/mailinfo.txt[] - -include::config/mailmap.txt[] - -include::config/man.txt[] - -include::config/merge.txt[] - -include::config/mergetool.txt[] - -include::config/notes.txt[] - -include::config/pack.txt[] - -include::config/pager.txt[] - -include::config/pretty.txt[] - -include::config/protocol.txt[] - -include::config/pull.txt[] - -include::config/push.txt[] - -include::config/rebase.txt[] - -include::config/receive.txt[] - -include::config/remote.txt[] - -include::config/remotes.txt[] - -include::config/repack.txt[] - -include::config/rerere.txt[] - -include::config/reset.txt[] - -include::config/sendemail.txt[] - -include::config/sequencer.txt[] - -include::config/showbranch.txt[] - -include::config/splitindex.txt[] - -include::config/ssh.txt[] - -include::config/status.txt[] - -include::config/stash.txt[] - -include::config/submodule.txt[] - -include::config/tag.txt[] - -include::config/transfer.txt[] - -include::config/uploadarchive.txt[] - -include::config/uploadpack.txt[] - -include::config/url.txt[] - -include::config/user.txt[] - -include::config/versionsort.txt[] - -include::config/web.txt[] - -include::config/worktree.txt[] diff --git a/date-formats.adoc b/date-formats.adoc new file mode 100644 index 000000000..e24517c49 --- /dev/null +++ b/date-formats.adoc @@ -0,0 +1,31 @@ +DATE FORMATS +------------ + +The `GIT_AUTHOR_DATE` and `GIT_COMMITTER_DATE` environment variables +support the following date formats: + +Git internal format:: + It is ` `, where + `` is the number of seconds since the UNIX epoch. + `` is a positive or negative offset from UTC. + For example CET (which is 1 hour ahead of UTC) is `+0100`. + +RFC 2822:: + The standard date format as described by RFC 2822, for example + `Thu, 07 Apr 2005 22:13:13 +0200`. + +ISO 8601:: + Time and date specified by the ISO 8601 standard, for example + `2005-04-07T22:13:13`. The parser accepts a space instead of the + `T` character as well. Fractional parts of a second will be ignored, + for example `2005-04-07T22:13:13.019` will be treated as + `2005-04-07T22:13:13`. ++ +NOTE: In addition, the date part is accepted in the following formats: +`YYYY.MM.DD`, `MM/DD/YYYY` and `DD.MM.YYYY`. + +ifdef::git-commit[] +In addition to recognizing all date formats above, the `--date` option +will also try to make sense of other, more human-centric date formats, +such as relative dates like "yesterday" or "last Friday at noon". +endif::git-commit[] diff --git a/date-formats.txt b/date-formats.txt deleted file mode 100644 index 6926e0a4c..000000000 --- a/date-formats.txt +++ /dev/null @@ -1,26 +0,0 @@ -DATE FORMATS ------------- - -The `GIT_AUTHOR_DATE`, `GIT_COMMITTER_DATE` environment variables -ifdef::git-commit[] -and the `--date` option -endif::git-commit[] -support the following date formats: - -Git internal format:: - It is `