{"thread":{"id":"47355","subject":"Bare repository fetch/push race condition","startedAt":"2017-11-30T10:28:22Z","lastAt":"2017-12-01T05:23:37Z","messageCount":2,"participants":["Dmitry Neverov"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"333847","messageId":"CAC+L6n3D1O+7U2F4sn6O+UD25t6hMGECMYZWgb45_FW6TBLz1g@mail.gmail.com","threadId":"47355","inReplyTo":null,"subject":"Bare repository fetch/push race condition","fromName":"Dmitry Neverov","fromEmail":"dmitry.neverov@gmail.com","sentAt":"2017-11-30T10:28:16Z","receivedAt":"2017-11-30T10:28:22Z","isPatch":false,"sender":{"key":"dmitry.neverov@gmail.com","avatar":null},"body":"It looks like there is a race condition between fetch and push in a\nbare repository in the following setup. There is a bare git repository\non a local file system. Some process pushes to this repository via\njgit. There is a cron task which pushes this repository to the backup\nremote repo over ssh. We observe the following in the reflog:\n\n6932a831843f4dbe3b394acde9adc9a8269b6cf1\n57b77b8c2a04029e7f5af4d3b7e36a3ba0c7cac9 XXX 1505903078 +0200    push:\nforced-update\n57b77b8c2a04029e7f5af4d3b7e36a3ba0c7cac9\n44a221b0271b9abc885dd6e54f691d5248c4171f XXX 1505905206 +0200    push:\nforced-update\n44a221b0271b9abc885dd6e54f691d5248c4171f\n57b77b8c2a04029e7f5af4d3b7e36a3ba0c7cac9 YYY    1505905217 +0200\nupdate by push\n\nWhere XXX is the process pushing via jgit and YYY is the cron task. It\nlooks like the cron task started a push when the ref was pointing to\n57b77b8c2a04029e7f5af4d3b7e36a3ba0c7cac9 and push finished when the\nref was already updated to 44a221b0271b9abc885dd6e54f691d5248c4171f.\nThe push unconditionally updated the local tracking branch back to the\ncommit 57b77b8c2a04029e7f5af4d3b7e36a3ba0c7cac9 and we lost the commit\n44a221b0271b9abc885dd6e54f691d5248c4171f since the next push from the\nlocal process created a new commit with\n57b77b8c2a04029e7f5af4d3b7e36a3ba0c7cac9 as a parent.\n\nShouldn't the update_ref at transport.c:308 specify the expected\nold hash, like this:\n\n    update_ref(\"update by push\", rs.dst, ref->new_oid.hash,\nref->old_oid.hash, 0, 0);\n\nat least for bare repositories?\n"},{"id":"333900","messageId":"94F893CA-8739-41BD-82F3-C68F9346E4B6@gmail.com","threadId":"47355","inReplyTo":"CAC+L6n3D1O+7U2F4sn6O+UD25t6hMGECMYZWgb45_FW6TBLz1g@mail.gmail.com","subject":"Re: Bare repository fetch/push race condition","fromName":"Dmitry Neverov","fromEmail":"dmitry.neverov@gmail.com","sentAt":"2017-12-01T05:23:28Z","receivedAt":"2017-12-01T05:23:37Z","isPatch":false,"sender":{"key":"dmitry.neverov@gmail.com","avatar":null},"body":"Sorry for misleading subject. It should be \"Race condition between pushing to and pushing from a bare repository\"\n"}]}