I know what git fetch does and how this command is used.
I am interested in the internals: how does Git determine the exact commits to transmit?
For example for the situation below
local repo:
A - B - C - D master
\ \- E - F feature1
\- G feature2
origin:
A - B - C - D - D1 - D2 master
\ \- E - F - F1 - F2 feature1
\- G - G1 feature2
git fetch would need to download commits D1, D2, F1, F2, and G1.
Naively, my git client could send a list of local commit SHAs (A, B, C, D, E, F, G) to the remote repository. The remote repository would find all its SHAs not on my list (D1, D2, F1, F2, G1) and send them back to me. For big repositories this would involve sending lots of data and doing a lot of computation. The data to send to remote repo would be proportional to the total number of commits.
I am sure a more clever approach is used.
Is sending just the SHAs of tip of each branch (D, F, G) sufficient? Tracking the parents the remote repo can determine the commits both repos share and determine just the missing ones. The data to send to remote repo would be proportional to the total number of (unmerged) branches, which normally is much much lower than the number of commits.
Does it work in all cases (branches behind, ahead, rebased)?
Any other ideas? I am expecting a beautiful solution based on graph theory :-)