Go to file
Jeff King 6294dcb49f lock_ref_sha1_basic: always fill old_oid while holding lock
Our basic strategy for taking a ref lock is:

  1. Create $ref.lock to take the lock

  2. Read the ref again while holding the lock (during which
     time we know that nobody else can be updating it).

  3. Compare the value we read to the expected "old_sha1"

The value we read in step (2) is returned to the caller via
the lock->old_oid field, who may use it for other purposes
(such as writing a reflog).

If we have no "old_sha1" (i.e., we are unconditionally
taking the lock), then we obviously must omit step 3. But we
_also_ omit step 2. This seems like a nice optimization, but
it means that the caller sees only whatever was left in
lock->old_oid from previous calls to resolve_ref_unsafe(),
which happened outside of the lock.

We can demonstrate this race pretty easily. Imagine you have
three commits, $one, $two, and $three. One script just flips
between $one and $two, without providing an old-sha1:

  while true; do
    git update-ref -m one refs/heads/foo $one
    git update-ref -m two refs/heads/foo $two
  done

Meanwhile, another script tries to set the value to $three,
also not using an old-sha1:

  while true; do
    git update-ref -m three refs/heads/foo $three
  done

If these run simultaneously, we'll see a lot of lock
contention, but each of the writes will succeed some of the
time. The reflog may record movements between any of the
three refs, but we would expect it to provide a consistent
log: the "from" field of each log entry should be the same
as the "to" field of the previous one.

But if we check this:

  perl -alne '
    print "mismatch on line $."
            if defined $last && $F[0] ne $last;
    $last = $F[1];
  ' .git/logs/refs/heads/foo

we'll see many mismatches. Why?

Because sometimes, in the time between lock_ref_sha1_basic
filling lock->old_oid via resolve_ref_unsafe() and it taking
the lock, there may be a complete write by another process.
And the "from" field in our reflog entry will be wrong, and
will refer to an older value.

This is probably quite rare in practice. It requires writers
which do not provide an old-sha1 value, and it is a very
quick race. However, it is easy to fix: we simply perform
step (2), the read-under-lock, whether we have an old-sha1
or not. Then the value we hand back to the caller is always
atomic.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-01-13 09:05:30 -08:00
Documentation Git 2.7-rc2 2015-12-22 14:46:01 -08:00
block-sha1 sha1: provide another level of indirection for the SHA-1 functions 2015-11-05 10:35:11 -08:00
builtin checkout,clone: check return value of create_symref 2016-01-12 11:11:52 -08:00
compat Merge branch 'js/emu-write-epipe-on-windows' 2015-12-22 14:45:16 -08:00
contrib Merge branch 'sg/completion-no-column' 2015-12-21 10:59:06 -08:00
ewah
git-gui
gitk-git Merge git://ozlabs.org/~paulus/gitk 2015-12-21 08:56:16 -08:00
gitweb
mergetools
perl git-svn: improve rebase/mkdirs performance 2015-11-10 01:35:01 +00:00
po l10n: ru.po: update Russian translation 2015-12-28 23:16:00 +08:00
ppc sha1: provide another level of indirection for the SHA-1 functions 2015-11-05 10:35:11 -08:00
refs lock_ref_sha1_basic: always fill old_oid while holding lock 2016-01-13 09:05:30 -08:00
t checkout,clone: check return value of create_symref 2016-01-12 11:11:52 -08:00
templates
vcs-svn
xdiff
.gitattributes
.gitignore
.mailmap
.travis.yml Add Travis CI support 2015-11-28 12:11:12 -05:00
COPYING
GIT-VERSION-GEN Git 2.7-rc2 2015-12-22 14:46:01 -08:00
INSTALL
LGPL-2.1
Makefile Merge branch 'dt/refs-backend-pre-vtable' 2015-12-08 14:14:49 -08:00
README
RelNotes Prepare for 2.6.5 2015-12-11 11:17:47 -08:00
abspath.c
aclocal.m4
advice.c
advice.h
alias.c
alloc.c
archive-tar.c
archive-zip.c
archive.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
archive.h
argv-array.c
argv-array.h
attr.c
attr.h
base85.c
bisect.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
bisect.h
blob.c
blob.h
branch.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
branch.h
builtin.h Merge branch 'sb/submodule-helper' 2015-10-05 12:30:19 -07:00
bulk-checkin.c
bulk-checkin.h
bundle.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
bundle.h
cache-tree.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
cache-tree.h
cache.h Merge branch 'bc/format-patch-null-from-line' 2015-12-21 10:59:08 -08:00
check-builtins.sh
check-racy.c
check_bindir
color.c
color.h
column.c
column.h
combine-diff.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
command-list.txt
commit-slab.h
commit.c Merge branch 'rs/pop-commit' into maint 2015-12-11 11:14:13 -08:00
commit.h
config.c Make error message after failing commit_lock_file() less confusing 2015-12-01 18:17:23 -05:00
config.mak.in
config.mak.uname
configure.ac Merge branch 'rc/configure-use-libs-when-checking-a-lib' into maint 2015-12-01 17:19:06 -05:00
connect.c get_remote_heads: convert to struct object_id 2015-11-20 08:02:05 -05:00
connect.h
connected.c
connected.h
convert.c
convert.h
copy.c
credential-cache--daemon.c credential-cache: new option to ignore sighup 2015-11-20 08:02:07 -05:00
credential-cache.c am, credential-cache: add angle brackets to usage string 2015-10-16 10:43:41 -07:00
credential-store.c credential-store: don't pass strerror to die_errno() 2015-12-16 10:27:12 -08:00
credential.c
credential.h
csum-file.c
csum-file.h
ctype.c
daemon.c Merge branch 'rs/daemon-plug-child-leak' into maint 2015-11-05 12:18:17 -08:00
date.c
decorate.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
decorate.h
delta.h
diff-delta.c
diff-lib.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
diff-no-index.c
diff.c Merge branch 'tk/sigchain-unnecessary-post-tempfile' 2015-10-29 13:59:18 -07:00
diff.h
diffcore-break.c
diffcore-delta.c
diffcore-order.c
diffcore-pickaxe.c
diffcore-rename.c
diffcore.h
dir.c Merge branch 'dt/name-hash-dir-entry-fix' into maint 2015-11-03 15:32:40 -08:00
dir.h
editor.c
entry.c
environment.c Merge branch 'jk/repository-extension' into maint 2015-11-03 15:32:25 -08:00
exec_cmd.c
exec_cmd.h
fast-import.c Merge branch 'sg/lock-file-commit-error' 2015-12-11 10:40:55 -08:00
fetch-pack.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
fetch-pack.h
fmt-merge-msg.h
fsck.c Merge branch 'bc/object-id' 2015-12-10 12:36:13 -08:00
fsck.h
generate-cmdlist.sh
gettext.c
gettext.h
git-add--interactive.perl
git-archimport.perl
git-bisect.sh
git-compat-util.h Merge branch 'jk/ident-loosen-getpwuid' 2015-12-21 10:59:07 -08:00
git-cvsexportcommit.perl
git-cvsimport.perl
git-cvsserver.perl
git-difftool--helper.sh
git-difftool.perl difftool: ignore symbolic links in use_wt_file 2015-10-29 13:43:10 -07:00
git-filter-branch.sh Merge branch 'jk/filter-branch-no-index' 2015-12-04 11:19:10 -08:00
git-instaweb.sh
git-merge-octopus.sh
git-merge-one-file.sh merge: detect delete/modechange conflict 2015-10-26 14:49:31 -07:00
git-merge-resolve.sh
git-mergetool--lib.sh
git-mergetool.sh
git-p4.py Merge branch 'ls/p4-keep-empty-commits' into maint 2015-12-15 09:34:19 -08:00
git-parse-remote.sh
git-quiltimport.sh
git-rebase--am.sh
git-rebase--interactive.sh rebase -i: remember merge options beyond continue actions 2015-12-11 12:44:44 -08:00
git-rebase--merge.sh
git-rebase.sh Merge branch 'jk/rebase-no-autostash' into maint 2015-12-08 14:05:01 -08:00
git-relink.perl
git-remote-testgit.sh
git-request-pull.sh
git-send-email.perl Merge branch 'jk/send-email-ssl-errors' 2015-12-21 10:59:06 -08:00
git-sh-i18n.sh
git-sh-setup.sh
git-stash.sh
git-submodule.sh Sync with 2.6.1 2015-10-05 13:20:08 -07:00
git-svn.perl
git-web--browse.sh
git.c Merge branch 'sb/submodule-helper' 2015-10-05 12:30:19 -07:00
git.rc
git.spec.in
gpg-interface.c
gpg-interface.h
graph.c
graph.h
grep.c
grep.h
hashmap.c
hashmap.h
help.c
help.h
hex.c
http-backend.c Convert struct object to object_id 2015-11-20 08:02:05 -05:00
http-fetch.c
http-push.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
http-walker.c
http.c Merge branch 'bc/object-id' 2015-12-10 12:36:13 -08:00
http.h http.c: use CURLOPT_RANGE for range requests 2015-11-02 14:18:06 -08:00
ident.c Merge branch 'jk/ident-loosen-getpwuid' 2015-12-21 10:59:07 -08:00
imap-send.c Merge branch 'js/imap-send-curl-compilation-fix' 2015-10-30 13:06:58 -07:00
khash.h
kwset.c
kwset.h
levenshtein.c
levenshtein.h
line-log.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
line-log.h
line-range.c
line-range.h
list-objects.c Convert struct object to object_id 2015-11-20 08:02:05 -05:00
list-objects.h
ll-merge.c Merge branch 'jk/war-on-sprintf' 2015-10-20 15:24:01 -07:00
ll-merge.h
lockfile.c
lockfile.h
log-tree.c format-patch: add an option to suppress commit hash 2015-12-15 10:03:40 -08:00
log-tree.h
mailinfo.c mailinfo: fix passing wrong address to git_mailinfo_config 2015-11-01 10:29:40 -08:00
mailinfo.h mailinfo: remove calls to exit() and die() deep in the callchain 2015-10-21 15:59:34 -07:00
mailmap.c
mailmap.h
match-trees.c
merge-blobs.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
merge-blobs.h
merge-recursive.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
merge-recursive.h
merge.c Convert struct object to object_id 2015-11-20 08:02:05 -05:00
mergesort.c
mergesort.h
name-hash.c name-hash: don't reuse cache_entry in dir_entry 2015-10-21 12:47:38 -07:00
notes-cache.c
notes-cache.h
notes-merge.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
notes-merge.h
notes-utils.c
notes-utils.h
notes.c
notes.h
object.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
object.h Remove get_object_hash. 2015-11-20 08:02:05 -05:00
pack-bitmap-write.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
pack-bitmap.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
pack-bitmap.h
pack-check.c verify_pack: do not ignore return value of verification function 2015-12-01 18:19:35 -05:00
pack-objects.c
pack-objects.h
pack-revindex.c Silence GCC's "cast of pointer to integer of a different size" warning 2015-10-26 13:24:03 -07:00
pack-revindex.h
pack-write.c
pack.h
pager.c Merge branch 'ti/glibc-stdio-mutex-from-signal-handler' into maint 2015-10-16 14:32:41 -07:00
parse-options-cb.c
parse-options.c parse-options: allow -h as a short option 2015-11-20 08:02:07 -05:00
parse-options.h parse-options: allow -h as a short option 2015-11-20 08:02:07 -05:00
patch-delta.c
patch-ids.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
patch-ids.h
path.c Merge branch 'dt/refs-backend-pre-vtable' 2015-12-08 14:14:49 -08:00
pathspec.c
pathspec.h
pkt-line.c
pkt-line.h
preload-index.c
pretty.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
prio-queue.c
prio-queue.h
progress.c
progress.h
prompt.c
prompt.h
quote.c quote: move comment before sq_quote_buf() 2015-10-07 15:12:01 -07:00
quote.h
reachable.c Merge branch 'js/gc-with-stale-symref' into maint 2015-10-20 15:22:42 -07:00
reachable.h
read-cache.c Merge branch 'dt/name-hash-dir-entry-fix' into maint 2015-11-03 15:32:40 -08:00
ref-filter.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
ref-filter.h
reflog-walk.c
reflog-walk.h
refs.c Merge branch 'bc/object-id' 2015-12-10 12:36:13 -08:00
refs.h create_symref: modernize variable names 2015-12-29 10:33:09 -08:00
remote-curl.c parse_fetch: convert to use struct object_id 2015-11-20 08:02:05 -05:00
remote-testsvn.c
remote.c remote: convert functions to struct object_id 2015-11-20 08:02:05 -05:00
remote.h ref_newer: convert to use struct object_id 2015-11-20 08:02:05 -05:00
replace_object.c
rerere.c
rerere.h
resolve-undo.c
resolve-undo.h
revision.c Merge branch 'sn/null-pointer-arith-in-mark-tree-uninteresting' into maint 2015-12-11 11:14:38 -08:00
revision.h format-patch: add an option to suppress commit hash 2015-12-15 10:03:40 -08:00
run-command.c Merge branch 'rs/daemon-plug-child-leak' into maint 2015-11-05 12:18:17 -08:00
run-command.h Merge branch 'rs/daemon-plug-child-leak' into maint 2015-11-05 12:18:17 -08:00
send-pack.c Convert struct ref to use object_id. 2015-11-20 08:02:05 -05:00
send-pack.h
sequencer.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
sequencer.h
server-info.c Convert struct object to object_id 2015-11-20 08:02:05 -05:00
setup.c Merge branch 'mk/submodule-gitdir-path' into maint 2015-11-03 15:32:35 -08:00
sh-i18n--envsubst.c
sha1-array.c
sha1-array.h
sha1-lookup.c
sha1-lookup.h
sha1_file.c Merge branch 'bc/format-patch-null-from-line' 2015-12-21 10:59:08 -08:00
sha1_name.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
shallow.c Merge branch 'rs/pop-commit' into maint 2015-12-11 11:14:13 -08:00
shell.c
shortlog.h
show-index.c usage: do not insist that standard input must come from a file 2015-10-16 15:27:52 -07:00
sideband.c
sideband.h
sigchain.c
sigchain.h
split-index.c
split-index.h
strbuf.c Merge branch 'tk/stripspace' 2015-10-26 15:55:20 -07:00
strbuf.h Merge branch 'tk/stripspace' 2015-10-26 15:55:20 -07:00
streaming.c
streaming.h
string-list.c
string-list.h
submodule-config.c push: add recurseSubmodules config option 2015-11-20 08:02:07 -05:00
submodule-config.h push: add recurseSubmodules config option 2015-11-20 08:02:07 -05:00
submodule.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
submodule.h push: add recurseSubmodules config option 2015-11-20 08:02:07 -05:00
symlinks.c
tag.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
tag.h
tar.h
tempfile.c
tempfile.h
test-chmtime.c
test-config.c
test-ctype.c
test-date.c
test-delta.c
test-dump-cache-tree.c
test-dump-split-index.c
test-dump-untracked-cache.c
test-genrandom.c
test-hashmap.c
test-index-version.c
test-line-buffer.c
test-match-trees.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
test-mergesort.c
test-mktemp.c
test-parse-options.c
test-path-utils.c test-path-utils.c: remove incorrect assumption 2015-10-08 18:03:50 -07:00
test-prio-queue.c
test-read-cache.c
test-regex.c
test-revision-walking.c
test-run-command.c
test-scrap-cache-tree.c
test-sha1-array.c
test-sha1.c
test-sha1.sh
test-sigchain.c
test-string-list.c
test-submodule-config.c
test-subprocess.c
test-svn-fe.c
test-urlmatch-normalization.c
test-wildmatch.c
thread-utils.c
thread-utils.h
trace.c
trace.h
trailer.c
trailer.h
transport-helper.c push_refs_with_export: convert to struct object_id 2015-11-20 08:02:05 -05:00
transport.c Merge branch 'bc/object-id' 2015-12-10 12:36:13 -08:00
transport.h Convert struct ref to use object_id. 2015-11-20 08:02:05 -05:00
tree-diff.c
tree-walk.c
tree-walk.h
tree.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
tree.h
unicode_width.h
unimplemented.sh
unix-socket.c
unix-socket.h
unpack-trees.c
unpack-trees.h
update_unicode.sh
upload-pack.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
url.c
url.h
urlmatch.c
urlmatch.h
usage.c
userdiff.c
userdiff.h
utf8.c
utf8.h
varint.c
varint.h
version.c
version.h
versioncmp.c
walker.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
walker.h
wildmatch.c
wildmatch.h
worktree.c worktree: add details to the worktree struct 2015-10-08 11:57:07 -07:00
worktree.h worktree: add details to the worktree struct 2015-10-08 11:57:07 -07:00
wrap-for-bin.sh test: facilitate debugging Git executables in tests with gdb 2015-10-30 14:02:38 -07:00
wrapper.c Merge branch 'jk/ident-loosen-getpwuid' 2015-12-21 10:59:07 -08:00
write_or_die.c
ws.c
wt-status.c Merge branch 'bc/object-id' 2015-12-10 12:36:13 -08:00
wt-status.h
xdiff-interface.c
xdiff-interface.h
zlib.c

README

////////////////////////////////////////////////////////////////

	Git - the stupid content tracker

////////////////////////////////////////////////////////////////

"git" can mean anything, depending on your mood.

 - random three-letter combination that is pronounceable, and not
   actually used by any common UNIX command.  The fact that it is a
   mispronunciation of "get" may or may not be relevant.
 - stupid. contemptible and despicable. simple. Take your pick from the
   dictionary of slang.
 - "global information tracker": you're in a good mood, and it actually
   works for you. Angels sing, and a light suddenly fills the room.
 - "goddamn idiotic truckload of sh*t": when it breaks

Git is a fast, scalable, distributed revision control system with an
unusually rich command set that provides both high-level operations
and full access to internals.

Git is an Open Source project covered by the GNU General Public
License version 2 (some parts of it are under different licenses,
compatible with the GPLv2). It was originally written by Linus
Torvalds with help of a group of hackers around the net.

Please read the file INSTALL for installation instructions.

See Documentation/gittutorial.txt to get started, then see
Documentation/giteveryday.txt for a useful minimum set of commands, and
Documentation/git-commandname.txt for documentation of each command.
If git has been correctly installed, then the tutorial can also be
read with "man gittutorial" or "git help tutorial", and the
documentation of each command with "man git-commandname" or "git help
commandname".

CVS users may also want to read Documentation/gitcvs-migration.txt
("man gitcvs-migration" or "git help cvs-migration" if git is
installed).

Many Git online resources are accessible from http://git-scm.com/
including full documentation and Git related tools.

The user discussion and development of Git take place on the Git
mailing list -- everyone is welcome to post bug reports, feature
requests, comments and patches to git@vger.kernel.org (read
Documentation/SubmittingPatches for instructions on patch submission).
To subscribe to the list, send an email with just "subscribe git" in
the body to majordomo@vger.kernel.org. The mailing list archives are
available at http://news.gmane.org/gmane.comp.version-control.git/,
http://marc.info/?l=git and other archival sites.

The maintainer frequently sends the "What's cooking" reports that
list the current status of various development topics to the mailing
list.  The discussion following them give a good reference for
project status, development direction and remaining tasks.