1. 16 10月, 2013 1 次提交
    • J
      remote: do not copy "origin" string literal · 11a6ba1c
      Jeff King 提交于
      Our default_remote_name starts at "origin", but may be
      overridden by the config file. In the former case, we
      allocate a new string, but in the latter case, we point to
      the remote name in an existing "struct branch".
      
      This gives the variable inconsistent free() semantics (we
      are sometimes responsible for freeing the string and
      sometimes pointing to somebody else's storage), and causes a
      small leak when the allocated string is overridden by
      config.
      
      We can fix both by simply dropping the extra copy and
      pointing to the string literal.
      Noticed-by: NFelipe Contreras <felipe.contreras@gmail.com>
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      11a6ba1c
  2. 27 8月, 2013 2 次提交
    • J
      status: always show tracking branch even no change · f223459b
      Jiang Xin 提交于
      In order to see what the current branch is tracking, one way is using
      "git branch -v -v", but branches other than the current are also
      reported. Another way is using "git status", such as:
      
          $ git status
          # On branch master
          # Your branch is ahead of 'origin/master' by 1 commit.
          ...
      
      But this will not work if there is no change between the current
      branch and its upstream. Always report upstream tracking info
      even if there is no difference, so that "git status" is consistent
      for checking tracking info for current branch. E.g.
      
          $ git status
          # On branch feature1
          # Your branch is up-to-date with 'github/feature1'.
          ...
      
          $ git status -bs
          ## feature1...github/feature1
          ...
      
          $ git checkout feature1
          Already on 'feature1'
          Your branch is up-to-date with 'github/feature1'.
          ...
      
      Also add some test cases in t6040.
      Signed-off-by: NJiang Xin <worldhello.net@gmail.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      f223459b
    • J
      branch: report invalid tracking branch as gone · f2e08739
      Jiang Xin 提交于
      Command "git branch -vv" will report tracking branches, but invalid
      tracking branches are also reported. This is because the function
      stat_tracking_info() can not distinguish invalid tracking branch
      from other cases which it would not like to report, such as
      there is no upstream settings at all, or nothing is changed between
      one branch and its upstream.
      
      Junio suggested missing upstream should be reported [1] like:
      
          $ git branch -v -v
            master    e67ac84 initial
          * topic     3fc0f2a [topicbase: gone] topic
      
          $ git status
          # On branch topic
          # Your branch is based on 'topicbase', but the upstream is gone.
          #   (use "git branch --unset-upstream" to fixup)
          ...
      
          $ git status -b -s
          ## topic...topicbase [gone]
          ...
      
      In order to do like that, we need to distinguish these three cases
      (i.e. no tracking, with configured but no longer valid tracking, and
      with tracking) in function stat_tracking_info(). So the refactored
      function stat_tracking_info() has three return values: -1 (with "gone"
      base), 0 (no base), and 1 (with base).
      
      If the caller does not like to report tracking info when nothing
      changed between the branch and its upstream, simply checks if
      num_theirs and num_ours are both 0.
      
      [1]: http://thread.gmane.org/gmane.comp.version-control.git/231830/focus=232288Suggested-by: NJunio C Hamano <gitster@pobox.com>
      Signed-off-by: NJiang Xin <worldhello.net@gmail.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      f2e08739
  3. 23 7月, 2013 3 次提交
    • J
      push --force-with-lease: tie it all together · 631b5ef2
      Junio C Hamano 提交于
      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: NJunio C Hamano <gitster@pobox.com>
      631b5ef2
    • J
      push --force-with-lease: implement logic to populate old_sha1_expect[] · 91048a95
      Junio C Hamano 提交于
      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
      patch.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      91048a95
    • J
      remote.c: add command line option parser for "--force-with-lease" · 28f5d176
      Junio C Hamano 提交于
      Update "git push" and "git send-pack" to parse this commnd line
      option.
      
      The intended sematics is:
      
       * "--force-with-lease" alone, without specifying the details, will
         protect _all_ remote refs that are going to be updated by
         requiring their current value to be the same as some reasonable
         default, unless otherwise specified;
      
       * "--force-with-lease=refname", without specifying the expected
         value, will protect that refname, if it is going to be updated,
         by requiring its current value to be the same as some reasonable
         default.
      
       * "--force-with-lease=refname:value" will protect that refname, if
         it is going to be updated, by requiring its current value to be
         the same as the specified value; and
      
       * "--no-force-with-lease" will cancel all the previous --force-with-lease on the
         command line.
      
      For now, "some reasonable default" is tentatively defined as "the
      value of the remote-tracking branch we have for the ref of the
      remote being updated", and it is an error if we do not have such a
      remote-tracking branch.  But this is known to be fragile, its use is
      not yet recommended, and hopefully we will find more reasonable
      default as we gain experience with this feature.  The manual marks
      the feature as experimental unless the expected value is specified
      explicitly for this reason.
      
      Because the command line options are parsed _before_ we know which
      remote we are pushing to, there needs further processing to the
      parsed data after we instantiate the transport object to:
      
       * expand "refname" given by the user to a full refname to be
         matched with the list of "struct ref" used in match_push_refs()
         and set_ref_status_for_push(); and
      
       * learning the actual local ref that is the remote-tracking branch
         for the specified remote ref.
      
      Further, some processing need to be deferred until we find the set
      of remote refs and match_push_refs() returns in order to find the
      ones that need to be checked after explicit ones have been processed
      for "--force-with-lease" (no specific details).
      
      These post-processing will be the topic of the next patch.
      
      This option was originally called "cas" (for "compare and swap"),
      the name which nobody liked because it was too technical.  The
      second attempt called it "lockref" (because it is conceptually like
      pushing after taking a lock) but the word "lock" was hated because
      it implied that it may reject push by others, which is not the way
      this option works.  This round calls it "force-with-lease".  You
      assume you took the lease on the ref when you fetched to decide what
      the rebased history should be, and you can push back only if the
      lease has not been broken.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      28f5d176
  4. 19 7月, 2013 1 次提交
    • M
      fetch: make --prune configurable · 737c5a9c
      Michael Schubert 提交于
      Without "git fetch --prune", remote-tracking branches for a branch
      the other side already has removed will stay forever.  Some people
      want to always run "git fetch --prune".
      
      To accommodate users who want to either prune always or when fetching
      from a particular remote, add two new configuration variables
      "fetch.prune" and "remote.<name>.prune":
      
       - "fetch.prune" allows to enable prune for all fetch operations.
      
       - "remote.<name>.prune" allows to change the behaviour per remote.
      
      The latter will naturally override the former, and the --[no-]prune
      option from the command line will override the configured default.
      
      Since --prune is a potentially destructive operation (Git doesn't
      keep reflogs for deleted references yet), we don't want to prune
      without users consent, so this configuration will not be on by
      default.
      Helped-by: NJunio C Hamano <gitster@pobox.com>
      Signed-off-by: NMichael Schubert <mschub@elegosoft.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      737c5a9c
  5. 09 7月, 2013 2 次提交
    • J
      cache.h: move remote/connect API out of it · 47a59185
      Junio C Hamano 提交于
      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: NJunio C Hamano <gitster@pobox.com>
      47a59185
    • B
      remote.c: avoid O(m*n) behavior in match_push_refs · f1bd15ab
      Brandon Casey 提交于
      When pushing using a matching refspec or a pattern refspec, each ref
      in the local repository must be paired with a ref advertised by the
      remote server.  This is accomplished by using the refspec to transform
      the name of the local ref into the name it should have in the remote
      repository, and then performing a linear search through the list of
      remote refs to see if the remote ref was advertised by the remote
      system.
      
      Each of these lookups has O(n) complexity and makes match_push_refs()
      be an O(m*n) operation, where m is the number of local refs and n is
      the number of remote refs.  If there are many refs 100,000+, then this
      ref matching can take a significant amount of time.  Let's prepare an
      index of the remote refs to allow searching in O(log n) time and
      reduce the complexity of match_push_refs() to O(m log n).
      
      We prepare the index lazily so that it is only created when necessary.
      So, there should be no impact when _not_ using a matching or pattern
      refspec, i.e. when pushing using only explicit refspecs.
      
      Dry-run push of a repository with 121,913 local and remote refs:
      
              before     after
      real    1m40.582s  0m0.804s
      user    1m39.914s  0m0.515s
      sys     0m0.125s   0m0.106s
      
      The creation of the index has overhead.  So, if there are very few
      local refs, then it could take longer to create the index than it
      would have taken to just perform n linear lookups into the remote
      ref space.  Using the index should provide some improvement when
      the number of local refs is roughly greater than the log of the
      number of remote refs (i.e. m >= log n).  The pathological case is
      when there is a single local ref and very many remote refs.
      
      Dry-run push of a repository with 121,913 remote refs and a single
      local ref:
      
              before    after
      real    0m0.525s  0m0.566s
      user    0m0.243s  0m0.279s
      sys     0m0.075s  0m0.099s
      
      Using an index takes 41 ms longer, or roughly 7.8% longer.
      
      Jeff King measured a no-op push of a single ref into a remote repo
      with 370,000 refs:
      
              before    after
      real    0m1.087s  0m1.156s
      user    0m1.344s  0m1.412s
      sys     0m0.288s  0m0.284s
      
      Using an index takes 69 ms longer, or roughly 6.3% longer.
      
      None of the measurements above required transferring any objects to
      the remote repository.  If the push required transferring objects and
      updating the refs in the remote repository, the impact of preparing
      the search index would be even smaller.
      
      A similar operation is performed in the reverse direction when pruning
      using a matching or pattern refspec.  Let's avoid O(m*n) behavior in
      the same way by lazily preparing an index on the local refs.
      Signed-off-by: NBrandon Casey <drafnel@gmail.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      f1bd15ab
  6. 23 6月, 2013 1 次提交
  7. 29 5月, 2013 1 次提交
  8. 03 4月, 2013 4 次提交
  9. 06 3月, 2013 1 次提交
    • J
      push: --follow-tags · c2aba155
      Junio C Hamano 提交于
      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: NJunio C Hamano <gitster@pobox.com>
      c2aba155
  10. 05 3月, 2013 1 次提交
    • J
      match_push_refs(): nobody sets src->peer_ref anymore · 703e8e65
      Junio C Hamano 提交于
      In ancient times, we used to disallow the same source ref to be
      pushed to more than one places, e.g. "git push there master:master
      master:naster" was disallowed.  We later lifted this restriction
      with db27ee63 (send-pack: allow the same source to be pushed
      more than once., 2005-08-06) and there no longer is anybody that
      sets peer_ref for the source side of the ref list in the push
      codepath since then.
      
      Remove one leftover no-op in a loop that iterates over the source
      side of ref list (i.e. our local ref) to see if it can/should be
      sent to a matching destination ref while skipping ones that is
      marked with peer_ref (which will never exist, so we do not skip
      anything).
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      703e8e65
  11. 08 2月, 2013 2 次提交
  12. 25 1月, 2013 3 次提交
    • J
      push: introduce REJECT_FETCH_FIRST and REJECT_NEEDS_FORCE · 75e5c0dc
      Junio C Hamano 提交于
      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
      appropriately.
      
      [jc: with help by Peff on message details]
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      75e5c0dc
    • J
      push: further simplify the logic to assign rejection reason · 0f4d498d
      Junio C Hamano 提交于
      First compute the reason why this push would fail if done without
      "--force", and then fail it by assigning that reason when the push
      was not forced (or if there is no reason to require force, allow it
      to succeed).
      
      Record the fact that the push was forced in the forced_update field
      only when the push would have failed without the option.
      
      The code becomes shorter, less repetitive and easier to read this
      way, especially given that the set of rejection reasons will be
      extended in a later patch.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      0f4d498d
    • J
      push: further clean up fields of "struct ref" · 5ece083f
      Junio C Hamano 提交于
      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: NJunio C Hamano <gitster@pobox.com>
      5ece083f
  13. 17 1月, 2013 1 次提交
    • J
      push: fix "refs/tags/ hierarchy cannot be updated without --force" · 256b9d70
      Junio C Hamano 提交于
      When pushing to update a branch with a commit that is not a
      descendant of the commit at the tip, a wrong message "already
      exists" was given, instead of the correct "non-fast-forward", if we
      do not have the object sitting in the destination repository at the
      tip of the ref we are updating.
      
      The primary cause of the bug is that the check in a new helper
      function is_forwardable() assumed both old and new objects are
      available and can be checked, which is not always the case.
      
      The way the caller uses the result of this function is also wrong.
      If the helper says "we do not want to let this push go through", the
      caller unconditionally translates it into "we blocked it because the
      destination already exists", which is not true at all in this case.
      
      Fix this by doing these three things:
      
       * Remove unnecessary not_forwardable from "struct ref"; it is only
         used inside set_ref_status_for_push();
      
       * Make "refs/tags/" the only hierarchy that cannot be replaced
         without --force;
      
       * Remove the misguided attempt to force that everything that
         updates an existing ref has to be a commit outside "refs/tags/"
         hierarchy.
      
      The policy last one tried to implement may later be resurrected and
      extended to ensure fast-forwardness (defined as "not losing
      objects", extending from the traditional "not losing commits from
      the resulting history") when objects that are not commit are
      involved (e.g. an annotated tag in hierarchies outside refs/tags),
      but such a logic belongs to "is this a fast-forward?" check that is
      done by ref_newer(); is_forwardable(), which is now removed, was not
      the right place to do so.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      256b9d70
  14. 12 12月, 2012 1 次提交
    • J
      fetch: ignore wildcarded refspecs that update local symbolic refs · f8fb971e
      Junio C Hamano 提交于
      In a repository cloned from somewhere else, you typically have a
      symbolic ref refs/remotes/origin/HEAD pointing at the 'master'
      remote-tracking ref that is next to it.  When fetching into such a
      repository with "git fetch --mirror" from another repository that
      was similarly cloned, the implied wildcard refspec refs/*:refs/*
      will end up asking to update refs/remotes/origin/HEAD with the
      object at refs/remotes/origin/HEAD at the remote side, while asking
      to update refs/remotes/origin/master the same way.  Depending on the
      order the two updates happen, the latter one would find that the
      value of the ref before it is updated has changed from what the code
      expects.
      
      When the user asks to update the underlying ref via the symbolic ref
      explicitly without using a wildcard refspec, e.g. "git fetch $there
      refs/heads/master:refs/remotes/origin/HEAD", we should still let him
      do so, but when expanding wildcard refs, it will result in a more
      intuitive outcome if we simply ignore local symbolic refs.
      
      As the purpose of the symbolic ref refs/remotes/origin/HEAD is to
      follow the ref it points at (e.g. refs/remotes/origin/master), its
      value would change when the underlying ref is updated.
      
      Earlier commit da3efdb1 (receive-pack: detect aliased updates which
      can occur with symrefs, 2010-04-19) fixed a similar issue for "git
      push".
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      f8fb971e
  15. 04 12月, 2012 2 次提交
  16. 02 12月, 2012 6 次提交
  17. 17 11月, 2012 1 次提交
  18. 20 10月, 2012 1 次提交
    • J
      get_fetch_map(): tighten checks on dest refs · 5c08c1f2
      Junio C Hamano 提交于
      The code to check the refname we store the fetched result locally did not
      bother checking the first 5 bytes of it, presumably assuming that it
      always begin with "refs/".  For a fetch refspec (or the result of applying
      wildcard on one), we always want the RHS to map to something inside
      "refs/" hierarchy, so let's spell that rule out in a more explicit way.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      5c08c1f2
  19. 04 7月, 2012 1 次提交
    • J
      push: don't guess at qualifying remote refs on deletion · 5742c82b
      Jeff King 提交于
      When we try to push a ref and the right-hand side of the
      refspec does not find a match, we try to create it. If it is
      not fully qualified, we try to guess where it would go in
      the refs hierarchy based on the left-hand source side. If
      the source side is not a ref, then we give up and give a
      long explanatory message.
      
      For deletions, however, this doesn't make any sense. We
      would never want to create on the remote side, and if an
      unqualified ref can't be matched, it is simply an error. The
      current code handles this already because the left-hand side
      is empty, and therefore does not give us a hint as to where
      the right-hand side should go, and we properly error out.
      Unfortunately, the error message is the long "we tried to
      qualify this, but the source side didn't let us guess"
      message, which is quite confusing.
      
      Instead, we can just be more succinct and say "we can't
      delete this because we couldn't find it". So before:
      
        $ git push origin :bogus
        error: unable to push to unqualified destination: bogus
        The destination refspec neither matches an existing ref on the remote nor
        begins with refs/, and we are unable to guess a prefix based on the source ref.
        error: failed to push some refs to '$URL'
      
      and now:
      
        $ git push origin :bogus
        error: unable to delete 'bogus': remote ref does not exist
        error: failed to push some refs to '$URL'
      
      It is tempting to also catch a fully-qualified ref like
      "refs/heads/bogus" and generate the same error message.
      However, that currently does not error out at all, and
      instead gets sent to the remote side, which typically
      generates a warning:
      
        $ git push origin:refs/heads/bogus
        remote: warning: Deleting a non-existent ref.
        To $URL
         - [deleted]         bogus
      
      While it would be nice to catch this error early, a
      client-side error would mean aborting the push entirely and
      changing push's exit code. For example, right now you can
      do:
      
        $ git push origin refs/heads/foo refs/heads/bar
      
      and end up in a state where "foo" and "bar" are deleted,
      whether both of them currently exist or not (and see an
      error only if we actually failed to contact the server).
      Generating an error would cause a regression for this use
      case.
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      5742c82b
  20. 23 5月, 2012 1 次提交
  21. 23 2月, 2012 4 次提交