{"thread":{"id":"4782","subject":"[RFH] further upload-pack/fetch-pack tweaks","startedAt":"2006-07-06T08:43:18Z","lastAt":"2006-07-06T08:43:18Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"23310","messageId":"7vejwz6s49.fsf@assigned-by-dhcp.cox.net","threadId":"4782","inReplyTo":null,"subject":"[RFH] further upload-pack/fetch-pack tweaks","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-07-06T08:43:18Z","receivedAt":"2006-07-06T08:43:18Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"I was reviewing this issue and have an updated attempt to solve\nthe issue slightly differently.  I think I have something\nworking but would like to borrow extra sets of eyeballs.\n\n    From: Junio C Hamano <junkio@cox.net>\n    Subject: [PATCH/RFC] upload-pack: stop \"ack continue\" when we know common commits for wanted refs\n    To: Ralf Baechle <ralf@linux-mips.org>\n    cc: git@vger.kernel.org, Linus Torvalds <torvalds@osdl.org>\n    Date: Fri, 26 May 2006 19:20:54 -0700\n    Message-ID: <7vfyiwi4xl.fsf@assigned-by-dhcp.cox.net>\n\n    When the downloader's repository has more roots than the server\n    side has, the \"have\" exchange to figure out recent common\n    commits ends up traversing the whole history of branches that\n    only exist on the downloader's side.  When the downloader is\n    asking for newer commits on the branch that exists on both ends,\n    this is totally unnecessary.\n\n    This adds logic to the server side to see if the wanted refs can\n    reach the \"have\" commits received so far, and stop issuing \"ack\n    continue\" once all of them can be reached from \"have\" commits.\n\nThe idea in the new implementation is to notice that the\ndownloader sent \"have\" for an object we do not know about, and\nwhen we already have some \"have\" from them and some \"want\" are\nstill not known if they are already reachable from these\n\"have\"s, we traverse the commit ancestry down to oldest \"have\"s\nso far (this is just a heuristic) to see if all of \"want\" have\nsome common ancestor with the other side.  When we know all\n\"want\" can be reachable by some \"have\" we have seen so far, we\nsend \"ACK continue\" when the downloader sends a \"have\" that we\ndo not have, to cause the downloader to stop traversing that\nfutile branch which leads to the root we do not have.  The code\nsits near the tip of \"pu\".\n\nI've started from a clone of git.git repository and tried to\nfetch \"todo\" branch from another clone that does not have\nanything but the \"todo\" branch.  So the downloader has five\nextra roots (one for git.git itself, one for gitk, one for\ngitweb, and one each for htmldocs and manpages).\n\n        # upstream is just \"todo\" branch and nothing else\n        git clone -n git.git upstream\n        cd upstream\n        mv .git/refs trash\n        mkdir -p .git/refs/heads .git/refs/tags\n        echo 'ref: refs/heads/master' >.git/HEAD\n        cat trash/heads/todo >.git/refs/heads/master\n        git repack -a -d\n        cd ..\n\n        # downloader has up-to-date git.git but stale \"todo\"\n\tgit clone -n git.git downloader\n        cd downloader\n        git checkout todo\n        git reset --hard HEAD~30\n        git repack -a -d\n\n        # try downloading things from upstream\n        git fetch-pack -k -v ../upstream master 2>/var/tmp/new.out\n\tgit fetch-pack -k -v --exec=old-git-upload-pack \\\n        \t../upstream master 2>/var/tmp/old.out\n\n\nIt does send smaller number of \"have\"s than the current code,\nbut I noticed that near the end of transfer, after it gets an\n\"ACK continue\" for a common commit on \"todo\" branch and an \"ACK\ncontinue\" for a not-common commit on \"master\" branch, it keeps\nsending the commits that are marked on the fetch-pack side as\nCOMMON_REF (so the last ref sent is v0.99^0 commit), although\nupload-pack has told the downloader that whatever is reachable\nfrom \"master\" branch are commits both sides agreed are common,\nso I suspect it should not go down that path that far to reach\nv0.99^0 commit.\n\nI have a feeling that either get_rev() or mark_common() logic is\nnot marking ancestors of commit that are known to be common\nproperly.  Does this ring a bell?\n"}]}