title: How does Git determine what objects need to be sent between repositories?
body: <p>I have looked <a href="http://git-scm.com/book/en/v2/Git-Internals-Transfer-Protocols">here</a> but couldn't quite figure out the things I was wondering about: how does <code>git push</code> or <code>git pull</code> figure out what commit objects are missing at the other side?</p>
  
  <p>Let's say we have a repository with the following commits: (letters stand in for SHA-1 IDs, <code>d</code> is <code>refs/heads/master</code>)</p>
  
  <pre><code>a -&gt; b -&gt; c -&gt; d
  </code></pre>
  
  <p>The remote, in contrast, has these:</p>
  
  <pre><code>a -&gt; e -&gt; f -&gt; g
  </code></pre>
  
  <p>According to the git document, the remote would tell us that its <code>refs/heads/master</code> is at <code>g</code>, but since we don't know that commit, that doesn't actually tell us anything. How is that enough to figure out the missing data?</p>
  
  <hr>
  
  <p>In the other direction, the document says:</p>
  
  <blockquote>
    <p>At this point, the fetch-pack process looks at what objects it has and responds with the objects that it needs by sending “want” and then the SHA-1 it wants. It sends <strong>all the objects it already has</strong> with “have” and then the SHA-1. At the end of this list, it writes “done” to initiate the upload-pack process to begin sending the packfile of the data it needs:</p>
  </blockquote>
  
  <p>this explains how the remote would determine what data to send, but wouldn't this impact pull performance on repositories with many objects? Otherwise, what is it that is actually meant in the text?</p>
  
  <hr>
  
  <p>Apparently the way of data transfer is very different depending on the direction (push vs pull). What and how are the challenges met by this design choice, and how am I to understand their descriptions in the document?</p>