This project is mirrored from Updated .
  1. 15 Sep, 2014 2 commits
    • Junio C Hamano's avatar
      signed push: add "pushee" header to push certificate · 9be89160
      Junio C Hamano authored
      Record the URL of the intended recipient for a push (after
      anonymizing it if it has authentication material) on a new "pushee
      URL" header.  Because the networking configuration (SSH-tunnels,
      proxies, etc.) on the pushing user's side varies, the receiving
      repository may not know the single canonical URL all the pushing
      users would refer it as (besides, many sites allow pushing over
      ssh://host/path and https://host/path protocols to the same
      repository but with different local part of the path).  So this
      value may not be reliably used for replay-attack prevention
      purposes, but this will still serve as a human readable hint to
      identify the repository the certificate refers to.
      Signed-off-by: default avatarJunio C Hamano <>
    • Junio C Hamano's avatar
      push: the beginning of "git push --signed" · a85b377d
      Junio C Hamano authored
      While signed tags and commits assert that the objects thusly signed
      came from you, who signed these objects, there is not a good way to
      assert that you wanted to have a particular object at the tip of a
      particular branch.  My signing v2.0.1 tag only means I want to call
      the version v2.0.1, and it does not mean I want to push it out to my
      'master' branch---it is likely that I only want it in 'maint', so
      the signature on the object alone is insufficient.
      The only assurance to you that 'maint' points at what I wanted to
      place there comes from your trust on the hosting site and my
      authentication with it, which cannot easily audited later.
      Introduce a mechanism that allows you to sign a "push certificate"
      (for the lack of better name) every time you push, asserting that
      what object you are pushing to update which ref that used to point
      at what other object.  Think of it as a cryptographic protection for
      ref updates, similar to signed tags/commits but working on an
      orthogonal axis.
      The basic flow based on this mechanism goes like this:
       1. You push out your work with "git push --signed".
       2. The sending side learns where the remote refs are as usual,
          together with what protocol extension the receiving end
          supports.  If the receiving end does not advertise the protocol
          extension "push-cert", an attempt to "git push --signed" fails.
          Otherwise, a text file, that looks like the following, is
          prepared in core:
      	certificate version 0.1
      	pusher Junio C Hamano <> 1315427886 -0700
      	7339ca65... 21580ecb... refs/heads/master
      	3793ac56... 12850bec... refs/heads/next
          The file begins with a few header lines, which may grow as we
          gain more experience.  The 'pusher' header records the name of
          the signer (the value of user.signingkey configuration variable,
          falling back to GIT_COMMITTER_{NAME|EMAIL}) and the time of the
          certificate generation.  After the header, a blank line follows,
          followed by a copy of the protocol message lines.
          Each line shows the old and the new object name at the tip of
          the ref this push tries to update, in the way identical to how
          the underlying "git push" protocol exchange tells the ref
          updates to the receiving end (by recording the "old" object
          name, the push certificate also protects against replaying).  It
          is expected that new command packet types other than the
          old-new-refname kind will be included in push certificate in the
          same way as would appear in the plain vanilla command packets in
          unsigned pushes.
          The user then is asked to sign this push certificate using GPG,
          formatted in a way similar to how signed tag objects are signed,
          and the result is sent to the other side (i.e. receive-pack).
          In the protocol exchange, this step comes immediately before the
          sender tells what the result of the push should be, which in
          turn comes before it sends the pack data.
       3. When the receiving end sees a push certificate, the certificate
          is written out as a blob.  The pre-receive hook can learn about
          the certificate by checking GIT_PUSH_CERT environment variable,
          which, if present, tells the object name of this blob, and make
          the decision to allow or reject this push.  Additionally, the
          post-receive hook can also look at the certificate, which may be
          a good place to log all the received certificates for later
      Because a push certificate carry the same information as the usual
      command packets in the protocol exchange, we can omit the latter
      when a push certificate is in use and reduce the protocol overhead.
      This however is not included in this patch to make it easier to
      review (in other words, the series at this step should never be
      released without the remainder of the series, as it implements an
      interim protocol that will be incompatible with the final one).
      As such, the documentation update for the protocol is left out of
      this step.
      Signed-off-by: default avatarJunio C Hamano <>
  2. 20 Aug, 2014 1 commit
  3. 24 Jul, 2014 1 commit
  4. 21 Jul, 2014 1 commit
  5. 18 Jul, 2014 1 commit
  6. 20 Jun, 2014 1 commit
    • Jeff King's avatar
      refactor skip_prefix to return a boolean · cf4fff57
      Jeff King authored
      The skip_prefix() function returns a pointer to the content
      past the prefix, or NULL if the prefix was not found. While
      this is nice and simple, in practice it makes it hard to use
      for two reasons:
        1. When you want to conditionally skip or keep the string
           as-is, you have to introduce a temporary variable.
           For example:
             tmp = skip_prefix(buf, "foo");
             if (tmp)
      	       buf = tmp;
        2. It is verbose to check the outcome in a conditional, as
           you need extra parentheses to silence compiler
           warnings. For example:
             if ((cp = skip_prefix(buf, "foo"))
      	       /* do something with cp */
      Both of these make it harder to use for long if-chains, and
      we tend to use starts_with() instead. However, the first line
      of "do something" is often to then skip forward in buf past
      the prefix, either using a magic constant or with an extra
      strlen(3) (which is generally computed at compile time, but
      means we are repeating ourselves).
      This patch refactors skip_prefix() to return a simple boolean,
      and to provide the pointer value as an out-parameter. If the
      prefix is not found, the out-parameter is untouched. This
      lets you write:
        if (skip_prefix(arg, "foo ", &arg))
        else if (skip_prefix(arg, "bar ", &arg))
      Signed-off-by: default avatarJeff King <>
      Signed-off-by: default avatarJunio C Hamano <>
  7. 05 Mar, 2014 1 commit
    • Jeff King's avatar
      push: detect local refspec errors early · ba928c13
      Jeff King authored
      When pushing, we do not even look at our push refspecs until
      after we have made contact with the remote receive-pack and
      gotten its list of refs. This means that we may go to some
      work, including asking the user to log in, before realizing
      we have simple errors like "git push origin matser".
      We cannot catch all refspec problems, since fully evaluating
      the refspecs requires knowing what the remote side has. But
      we can do a quick sanity check of the local side and catch a
      few simple error cases.
      Signed-off-by: default avatarJeff King <>
      Signed-off-by: default avatarJunio C Hamano <>
  8. 11 Dec, 2013 6 commits
  9. 09 Dec, 2013 1 commit
  10. 05 Dec, 2013 1 commit
    • Christian Couder's avatar
      replace {pre,suf}fixcmp() with {starts,ends}_with() · 59556548
      Christian Couder authored
      Leaving only the function definitions and declarations so that any
      new topic in flight can still make use of the old functions, replace
      existing uses of the prefixcmp() and suffixcmp() with new API
      The change can be recreated by mechanically applying this:
          $ git grep -l -e prefixcmp -e suffixcmp -- \*.c |
            grep -v strbuf\\.c |
            xargs perl -pi -e '
      on the result of preparatory changes in this series.
      Signed-off-by: Christian Couder's avatarChristian Couder <>
      Signed-off-by: default avatarJunio C Hamano <>
  11. 07 Aug, 2013 1 commit
    • Junio C Hamano's avatar
      fetch: work around "transport-take-over" hack · b26ed430
      Junio C Hamano authored
      A Git-aware "connect" transport allows the "transport_take_over" to
      redirect generic transport requests like fetch(), push_refs() and
      get_refs_list() to the native Git transport handling methods.  The
      take-over process replaces transport->data with a fake data that
      these method implementations understand.
      While this hack works OK for a single request, it breaks when the
      transport needs to make more than one requests.  transport->data
      that used to hold necessary information for the specific helper to
      work correctly is destroyed during the take-over process.
      One codepath that this matters is "git fetch" in auto-follow mode;
      when it does not get all the tags that ought to point at the history
      it got (which can be determined by looking at the peeled tags in the
      initial advertisement) from the primary transfer, it internally
      makes a second request to complete the fetch.  Because "take-over"
      hack has already destroyed the data necessary to talk to the
      transport helper by the time this happens, the second request cannot
      make a request to the helper to make another connection to fetch
      these additional tags.
      Mark such a transport as "cannot_reuse", and use a separate
      transport to perform the backfill fetch in order to work around
      this breakage.
      Note that this problem does not manifest itself when running t5802,
      because our upload-pack gives you all the necessary auto-followed
      tags during the primary transfer.  You would need to step through
      "git fetch" in a debugger, stop immediately after the primary
      transfer finishes and writes these auto-followed tags, remove the
      tag references and repack/prune the repository to convince the
      "find-non-local-tags" procedure that the primary transfer failed to
      give us all the necessary tags, and then let it continue, in order
      to trigger the bug in the secondary transfer this patch fixes.
      Signed-off-by: default avatarJunio C Hamano <>
  12. 23 Jul, 2013 2 commits
    • Junio C Hamano's avatar
      push --force-with-lease: tie it all together · 631b5ef2
      Junio C Hamano authored
      This teaches the deepest part of the callchain for "git push" (and
      "git send-pack") to enforce "the old value of the ref must be this,
      otherwise fail this push" (aka "compare-and-swap" / "--lockref").
      Signed-off-by: default avatarJunio C Hamano <>
    • Junio C Hamano's avatar
      push --force-with-lease: implement logic to populate old_sha1_expect[] · 91048a95
      Junio C Hamano authored
      This plugs the push_cas_option data collected by the command line
      option parser to the transport system with a new function
      apply_push_cas(), which is called after match_push_refs() has
      already been called.
      At this point, we know which remote we are talking to, and what
      remote refs we are going to update, so we can fill in the details
      that may have been missing from the command line, such as
       (1) what abbreviated refname the user gave us matches the actual
           refname at the remote; and
       (2) which remote-tracking branch in our local repository to read
           the value of the object to expect at the remote.
      to populate the old_sha1_expect[] field of each of the remote ref.
      As stated in the documentation, the use of remote-tracking branch
      as the default is a tentative one, and we may come up with a better
      logic as we gain experience.
      Still nobody uses this information, which is the topic of the next
      Signed-off-by: default avatarJunio C Hamano <>
  13. 08 Jul, 2013 1 commit
    • Junio C Hamano's avatar
      cache.h: move remote/connect API out of it · 47a59185
      Junio C Hamano authored
      The definition of "struct ref" in "cache.h", a header file so
      central to the system, always confused me.  This structure is not
      about the local ref used by sha1-name API to name local objects.
      It is what refspecs are expanded into, after finding out what refs
      the other side has, to define what refs are updated after object
      transfer succeeds to what values.  It belongs to "remote.h" together
      with "struct refspec".
      While we are at it, also move the types and functions related to the
      Git transport connection to a new header file connect.h
      Signed-off-by: default avatarJunio C Hamano <>
  14. 18 Jun, 2013 1 commit
  15. 28 May, 2013 1 commit
    • Duy Nguyen's avatar
      clone: open a shortcut for connectivity check · c6807a40
      Duy Nguyen authored
      In order to make sure the cloned repository is good, we run "rev-list
      --objects --not --all $new_refs" on the repository. This is expensive
      on large repositories. This patch attempts to mitigate the impact in
      this special case.
      In the "good" clone case, we only have one pack. If all of the
      following are met, we can be sure that all objects reachable from the
      new refs exist, which is the intention of running "rev-list ...":
       - all refs point to an object in the pack
       - there are no dangling pointers in any object in the pack
       - no objects in the pack point to objects outside the pack
      The second and third checks can be done with the help of index-pack as
      a slight variation of --strict check (which introduces a new condition
      for the shortcut: pack transfer must be used and the number of objects
      large enough to call index-pack). The first is checked in
      check_everything_connected after we get an "ok" from index-pack.
      "index-pack + new checks" is still faster than the current "index-pack
      + rev-list", which is the whole point of this patch. If any of the
      conditions fail, we fall back to the good old but expensive "rev-list
      ..". In that case it's even more expensive because we have to pay for
      the new checks in index-pack. But that should only happen when the
      other side is either buggy or malicious.
      Cloning linux-2.6 over file://
              before         after
      real    3m25.693s      2m53.050s
      user    5m2.037s       4m42.396s
      sys     0m13.750s      0m16.574s
      A more realistic test with ssh:// over wireless
              before         after
      real    11m26.629s     10m4.213s
      user    5m43.196s      5m19.444s
      sys     0m35.812s      0m37.630s
      This shortcut is not applied to shallow clones, partly because shallow
      clones should have no more objects than a usual fetch and the cost of
      rev-list is acceptable, partly to avoid dealing with corner cases when
      grafting is involved.
      This shortcut does not apply to unpack-objects code path either
      because the number of objects must be small in order to trigger that
      code path.
      Signed-off-by: Duy Nguyen's avatarNguyễn Thái Ngọc Duy <>
      Signed-off-by: default avatarJunio C Hamano <>
  16. 25 Mar, 2013 1 commit
  17. 21 Mar, 2013 1 commit
  18. 05 Mar, 2013 1 commit
    • Junio C Hamano's avatar
      push: --follow-tags · c2aba155
      Junio C Hamano authored
      The new option "--follow-tags" tells "git push" to push annotated
      tags that are missing from the other side and that can be reached by
      the history that is otherwise pushed out.
      For example, if you are using the "simple", "current", or "upstream"
      push, you would ordinarily push the history leading to the commit at
      your current HEAD and nothing else.  With this option, you would
      also push all annotated tags that can be reached from that commit to
      the other side.
      Signed-off-by: default avatarJunio C Hamano <>
  19. 24 Feb, 2013 1 commit
  20. 07 Feb, 2013 1 commit
    • Junio C Hamano's avatar
      fetch: use struct ref to represent refs to be fetched · f2db854d
      Junio C Hamano authored
      Even though "git fetch" has full infrastructure to parse refspecs to
      be fetched and match them against the list of refs to come up with
      the final list of refs to be fetched, the list of refs that are
      requested to be fetched were internally converted to a plain list of
      strings at the transport layer and then passed to the underlying
      fetch-pack driver.
      Stop this conversion and instead pass around an array of refs.
      Signed-off-by: default avatarJunio C Hamano <>
  21. 31 Jan, 2013 1 commit
  22. 24 Jan, 2013 2 commits
    • Junio C Hamano's avatar
      push: introduce REJECT_FETCH_FIRST and REJECT_NEEDS_FORCE · 75e5c0dc
      Junio C Hamano authored
      When we push to update an existing ref, if:
       * the object at the tip of the remote is not a commit; or
       * the object we are pushing is not a commit,
      it won't be correct to suggest to fetch, integrate and push again,
      as the old and new objects will not "merge".  We should explain that
      the push must be forced when there is a non-committish object is
      involved in such a case.
      If we do not have the current object at the tip of the remote, we do
      not even know that object, when fetched, is something that can be
      merged.  In such a case, suggesting to pull first just like
      non-fast-forward case may not be technically correct, but in
      practice, most such failures are seen when you try to push your work
      to a branch without knowing that somebody else already pushed to
      update the same branch since you forked, so "pull first" would work
      as a suggestion most of the time.  And if the object at the tip is
      not a commit, "pull first" will fail, without making any permanent
      damage.  As a side effect, it also makes the error message the user
      will get during the next "push" attempt easier to understand, now
      the user is aware that a non-commit object is involved.
      In these cases, the current code already rejects such a push on the
      client end, but we used the same error and advice messages as the
      ones used when rejecting a non-fast-forward push, i.e. pull from
      there and integrate before pushing again.
      Introduce new rejection reasons and reword the messages
      [jc: with help by Peff on message details]
      Signed-off-by: default avatarJunio C Hamano <>
    • Junio C Hamano's avatar
      push: further clean up fields of "struct ref" · 5ece083f
      Junio C Hamano authored
      The "nonfastforward" and "update" fields are only used while
      deciding what value to assign to the "status" locally in a single
      function.  Remove them from the "struct ref".
      The "requires_force" field is not used to decide if the proposed
      update requires a --force option to succeed, or to record such a
      decision made elsewhere.  It is used by status reporting code that
      the particular update was "forced".  Rename it to "forced_update",
      and move the code to assign to it around to further clarify how it
      is used and what it is used for.
      Signed-off-by: default avatarJunio C Hamano <>
  23. 18 Jan, 2013 1 commit
    • Aaron Schrab's avatar
      push: Add support for pre-push hooks · ec55559f
      Aaron Schrab authored
      Add support for a pre-push hook which can be used to determine if the
      set of refs to be pushed is suitable for the target repository.  The
      hook is run with two arguments specifying the name and location of the
      destination repository.
      Information about what is to be pushed is provided by sending lines of
      the following form to the hook's standard input:
        <local ref> SP <local sha1> SP <remote ref> SP <remote sha1> LF
      If the hook exits with a non-zero status, the push will be aborted.
      This will allow the script to determine if the push is acceptable based
      on the target repository and branch(es), the commits which are to be
      pushed, and even the source branches in some cases.
      Signed-off-by: Aaron Schrab's avatarAaron Schrab <>
      Signed-off-by: default avatarJunio C Hamano <>
  24. 02 Dec, 2012 4 commits
  25. 12 Sep, 2012 2 commits
  26. 30 Mar, 2012 2 commits
  27. 28 Mar, 2012 1 commit