{"thread":{"id":"5239","subject":"Git network protocol","startedAt":"2006-08-14T06:21:17Z","lastAt":"2006-08-15T09:14:10Z","messageCount":5,"participants":["Josef \"Jeff\" Sipek","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"25222","messageId":"20060814062117.GC10476@josefsipek.net","threadId":"5239","inReplyTo":null,"subject":"Git network protocol","fromName":"Josef \"Jeff\" Sipek","fromEmail":"jeffpc@josefsipek.net","sentAt":"2006-08-14T06:21:17Z","receivedAt":"2006-08-14T06:21:17Z","isPatch":false,"sender":{"key":"jeffpc@josefsipek.net","avatar":null},"body":"Hello,\n\nI'm trying to implement the git protocol, and I am having a bit of an issue\nwith the lack of information available about it (please correct me if I\nmissed some source of information.)\n\nI understand the basic format of the protocol, however I'm not sure what\n\"command\" can follow what. I also noticed some odd inconsistencies (or maybe\nI just don't see the pattern yet.) For example, a git-clone generates this\ntraffic:\n\nC: git-upload-pack ....\nS: SHA1 HEAD....\nS: SHA1 refs/heads/master\nS: flush\nC: want SHA1...\nC: want SHA1... (it wants the same SHA1 twice!)\nC: flush\nC: done\nS: NAK\nS: the pack...\n\nThen, when it is time to git-fetch a new commit, I get:\n\nC: git-upload-pack ....\nS: SHA1 HEAD....\nS: SHA1 refs/heads/master\nS: flush\nC: want SHA1...\nC: flush\nC: have SHA1\nC: done\nS: ACK SHA1 continue\nS: ACK SHA1 (same hash)\nS: the pack...\n\nThen, if I try to git-fetch but there is nothing new, I get:\n\nC: git-upload-pack ....\nS: SHA1 HEAD....\nS: SHA1 refs/heads/master\nS: flush\nC: flush\n<client closes connection>\n\nSo, I can _assume_ that \"done\" tells the server that it is time to make a\npack. Why does the server use NAK during the clone operation, but ACK\nduring fetch? Why does the server ACK the same SHA1 twice? And why does the\nclient \"want\" the same SHA1 twice? It just seems odd.\n\nI think it would be great if there was some kind of description somewhere\nthat detailed the protocol. Also, the daemon source isn't the prettiest\nthing in the world.\n\nThanks,\nJosef \"Jeff\" Sipek.\n\n-- \nReality is merely an illusion, albeit a very persistent one.\n\t\t- Albert Einstein\n"},{"id":"25225","messageId":"7vk65bg6na.fsf@assigned-by-dhcp.cox.net","threadId":"5239","inReplyTo":"20060814062117.GC10476@josefsipek.net","subject":"Re: Git network protocol","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-08-14T06:42:33Z","receivedAt":"2006-08-14T06:42:33Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"jeffpc@josefsipek.net (Josef \"Jeff\" Sipek) writes:\n\n> I'm trying to implement the git protocol, and I am having a bit of an issue\n> with the lack of information available about it (please correct me if I\n> missed some source of information.)\n\nDocumentation/technical/pack-protocol.txt, and \"git show 1bd8c8f0\".\n\n> So, I can _assume_ that \"done\" tells the server that it is time to make a\n> pack. Why does the server use NAK during the clone operation, but ACK\n> during fetch? Why does the server ACK the same SHA1 twice? And why does the\n> client \"want\" the same SHA1 twice? It just seems odd.\n\nDuring the initial \"SHA-1 name\"/\"want\" exchange, the server and\nthe client negotiate the protocol extension (the document needs\nto be updated at least for \"multi-ack\" extension).\n\nAfter that, the client and the server try to determine what\ncommits the client has that are recent ancestors of \"want\"\ncommits.  This exchange is done by client sending bunch of\n\"have\" to the server.  The server responds \"ACK\" (in the\noriginal protocol) to say \"I've seen enough and know a common\nancestor to use\".  In multi-ack protocol (which is used in\nmodern git, v0.99.9 and later), the server can respond \"ACK\ncontinue\" to say \"I've seen enough on that branch so do not\nbother sending 'have's for its ancestors, but do keep sending\nfrom other branch.\"  If the server does not feel it saw enough,\nit does not send either.\n\nThe client can send \"flush\" -- this asks the server to give NAK\nif more \"have\"s need to be sent.  If there is no more \"have\"s to\nbe sent, \"done\" is sent.\n\nThe protocol streams; if you see an ACK from server it does not\nusually mean it is ACKing the last 'have' client has sent.\n"},{"id":"25325","messageId":"20060814234826.GA21861@josefsipek.net","threadId":"5239","inReplyTo":"7vk65bg6na.fsf@assigned-by-dhcp.cox.net","subject":"Re: Git network protocol","fromName":"Josef \"Jeff\" Sipek","fromEmail":"jeffpc@josefsipek.net","sentAt":"2006-08-14T23:48:26Z","receivedAt":"2006-08-14T23:48:26Z","isPatch":false,"sender":{"key":"jeffpc@josefsipek.net","avatar":null},"body":"On Sun, Aug 13, 2006 at 11:42:33PM -0700, Junio C Hamano wrote:\n> jeffpc@josefsipek.net (Josef \"Jeff\" Sipek) writes:\n> \n> > I'm trying to implement the git protocol, and I am having a bit of an issue\n> > with the lack of information available about it (please correct me if I\n> > missed some source of information.)\n> \n> Documentation/technical/pack-protocol.txt\n\nThis is pretty much a vague example - or at least it feels vague if you\ndon't know the protocol. After reading the source, and your description, the\nexample makes a lot more sense.\n\n> \"git show 1bd8c8f0\".\n\nNeat.\n\n> After that, the client and the server try to determine what\n> commits the client has that are recent ancestors of \"want\"\n> commits.  This exchange is done by client sending bunch of\n> \"have\" to the server.  The server responds \"ACK\" (in the\n> original protocol) to say \"I've seen enough and know a common\n> ancestor to use\".  In multi-ack protocol (which is used in\n> modern git, v0.99.9 and later), the server can respond \"ACK\n> continue\" to say \"I've seen enough on that branch so do not\n> bother sending 'have's for its ancestors, but do keep sending\n> from other branch.\"  If the server does not feel it saw enough,\n> it does not send either.\n\nSo, if I understand this correctly, multi_ack allows for multiple branches\nto be fetched using the same connection?\n\n> The protocol streams; if you see an ACK from server it does not\n> usually mean it is ACKing the last 'have' client has sent.\n\nYeah, makes sense. Doing things over lo does things like that - I'm not sure\nwhy I didn't realize it earlier.\n\nThanks,\nJosef \"Jeff\" Sipek.\n\n-- \nDon't drink and derive. Alcohol and algebra don't mix.\n"},{"id":"25332","messageId":"7vwt9aak5i.fsf@assigned-by-dhcp.cox.net","threadId":"5239","inReplyTo":"20060814234826.GA21861@josefsipek.net","subject":"Re: Git network protocol","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-08-15T00:59:37Z","receivedAt":"2006-08-15T00:59:37Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"jeffpc@josefsipek.net (Josef \"Jeff\" Sipek) writes:\n\n> So, if I understand this correctly, multi_ack allows for multiple branches\n> to be fetched using the same connection?\n\nThe original protocol without extension already allowed it.\nSuppose the global history was like this:\n\n       o-----------------------o---o---o---o---o---o---o---c---c---c\n      /\n o---o---o---o---o---o---o---o---s---s---s\n\nwhere the server side had 's', the client side had 'c', and both\nof them had 'o'.  The objective is to update client with three 's'\ncommits.\n\nThe exchange would go like this without multi-ack:\n\n\tS: SHA-1 name1 -- for the rightmost 'o' on the top branch\n        S: SHA-2 name2 -- for the rightmost 's' on the bottom branch\n\tC: want SHA-2 -- ask for the second branch tip\n\tC: have SHA1 -- the rightmost 'c' on the top branch\n\tC: have SHA1 -- the parent of the above\n\tC: have SHA1 -- the parent of the above\n        C: have SHA1 -- the parent of the above, rightmost 'o' on the top.\n        C: ... more have from the top branch.\n\tS: ACK -- for the rightmost 'o' on the top branch\n\nDuring this exchange, the server learns that the client and the\nserver shares the rightmost 'o' on the top branch, but does not\nlearn about all the 'o' commits on the bottom branch, so it ends\nup sending everything from the fork point to complete three 's'\ncommits.\n\nThe multi-ack extension was invented by Johannes to improve this\nexchange.  It changes the protocol to let the server ACK with\n\"ACK continue\".  After that, the client is expected to stop\ntraversing the parents of ACK-continue'd commit -- so it has a\nchance to send the rightmost 'o' on the bottom branch.  When the\nserver sees it, it again gives an ACK, and the client soon runs\nout have's to send and says \"done\".  In this case, the server\nwould have the rightmost 'o' commits on both branches to work\nout the minimum set of objects to complete three 's' commits\nthat are missing from the client.\n"},{"id":"25352","messageId":"20060815091410.GA28369@josefsipek.net","threadId":"5239","inReplyTo":"7vwt9aak5i.fsf@assigned-by-dhcp.cox.net","subject":"Re: Git network protocol","fromName":"Josef \"Jeff\" Sipek","fromEmail":"jeffpc@josefsipek.net","sentAt":"2006-08-15T09:14:10Z","receivedAt":"2006-08-15T09:14:10Z","isPatch":false,"sender":{"key":"jeffpc@josefsipek.net","avatar":null},"body":"On Mon, Aug 14, 2006 at 05:59:37PM -0700, Junio C Hamano wrote:\n> jeffpc@josefsipek.net (Josef \"Jeff\" Sipek) writes:\n> \n> > So, if I understand this correctly, multi_ack allows for multiple branches\n> > to be fetched using the same connection?\n> \n> The original protocol without extension already allowed it.\n> Suppose the global history was like this:\n...\n\nThanks. That helped a lot.\n\nJosef \"Jeff\" Sipek.\n\n-- \nLinux, n.:\n  Generous programmers from around the world all join forces to help you\n  shoot yourself in the foot for free. \n"}]}