Setup and Config
Getting and Creating Projects
Basic Snapshotting
Branching and Merging
Sharing and Updating Projects
Inspection and Comparison
Patching
Debugging
External Systems
Server Admin
Guides
- gitattributes
- Command-line interface conventions
- Everyday Git
- Frequently Asked Questions (FAQ)
- Glossary
- Hooks
- gitignore
- gitmodules
- Revisions
- Submodules
- Tutorial
- Workflows
- All guides...
Administration
Plumbing Commands
- 2.3.10 → 2.5.6 no changes
-
2.2.3
2015-09-04
- 2.1.4 no changes
-
2.0.5
2014-12-17
The lockfile API serves two purposes:
-
Mutual exclusion and atomic file updates. When we want to change a file, we create a lockfile
<filename>.lock
, write the new file contents into it, and then rename the lockfile to its final destination<filename>
. We create the<filename>.lock
file withO_CREAT|O_EXCL
so that we can notice and fail if somebody else has already locked the file, then atomically rename the lockfile to its final destination to commit the changes and unlock the file. -
Automatic cruft removal. If the program exits after we lock a file but before the changes have been committed, we want to make sure that we remove the lockfile. This is done by remembering the lockfiles we have created in a linked list and setting up an
atexit(3)
handler and a signal handler that clean up the lockfiles. This mechanism ensures that outstanding lockfiles are cleaned up if the program exits (including whendie()
is called) or if the program dies on a signal.
Please note that lockfiles only block other writers. Readers do not
block, but they are guaranteed to see either the old contents of the
file or the new contents of the file (assuming that the filesystem
implements rename(2)
atomically).
Calling sequence
The caller:
-
Allocates a
struct lock_file
either as a static variable or on the heap, initialized to zeros. Once you use the structure to call thehold_lock_file_*
family of functions, it belongs to the lockfile subsystem and its storage must remain valid throughout the life of the program (i.e. you cannot use an on-stack variable to hold this structure). -
Attempts to create a lockfile by passing that variable and the path of the final destination (e.g.
$GIT_DIR/index
) tohold_lock_file_for_update
orhold_lock_file_for_append
. -
Writes new content for the destination file by either:
-
writing to the file descriptor returned by the
hold_lock_file_*
functions (also available vialock->fd
). -
calling
fdopen_lock_file
to get aFILE
pointer for the open file and writing to the file using stdio.
When finished writing, the caller can:
-
Close the file descriptor and rename the lockfile to its final destination by calling
commit_lock_file
orcommit_lock_file_to
. -
Close the file descriptor and remove the lockfile by calling
rollback_lock_file
. -
Close the file descriptor without removing or renaming the lockfile by calling
close_lock_file
, and later callcommit_lock_file
,commit_lock_file_to
,rollback_lock_file
, orreopen_lock_file
.
Even after the lockfile is committed or rolled back, the lock_file
object must not be freed or altered by the caller. However, it may be
reused; just pass it to another call of hold_lock_file_for_update
or
hold_lock_file_for_append
.
If the program exits before you have called one of commit_lock_file
,
commit_lock_file_to
, rollback_lock_file
, or close_lock_file
, an
atexit(3)
handler will close and remove the lockfile, rolling back
any uncommitted changes.
If you need to close the file descriptor you obtained from a
hold_lock_file_*
function yourself, do so by calling
close_lock_file
. You should never call close(2)
or fclose(3)
yourself! Otherwise the struct lock_file
structure would still think
that the file descriptor needs to be closed, and a commit or rollback
would result in duplicate calls to close(2)
. Worse yet, if you close
and then later open another file descriptor for a completely different
purpose, then a commit or rollback might close that unrelated file
descriptor.
Error handling
The hold_lock_file_*
functions return a file descriptor on success
or -1 on failure (unless LOCK_DIE_ON_ERROR
is used; see below). On
errors, errno
describes the reason for failure. Errors can be
reported by passing errno
to one of the following helper functions:
Similarly, commit_lock_file
, commit_lock_file_to
, and
close_lock_file
return 0 on success. On failure they set errno
appropriately, do their best to roll back the lockfile, and return -1.
Flags
The following flags can be passed to hold_lock_file_for_update
or
hold_lock_file_for_append
:
- LOCK_NO_DEREF
-
Usually symbolic links in the destination path are resolved and the lockfile is created by adding ".lock" to the resolved path. If
LOCK_NO_DEREF
is set, then the lockfile is created by adding ".lock" to the path argument itself. This option is used, for example, when locking a symbolic reference, which for backwards-compatibility reasons can be a symbolic link containing the name of the referred-to-reference. - LOCK_DIE_ON_ERROR
-
If a lock is already taken for the file,
die()
with an error message. If this option is not specified, trying to lock a file that is already locked returns -1 to the caller.
The functions
- hold_lock_file_for_update
-
Take a pointer to
struct lock_file
, the path of the file to be locked (e.g.$GIT_DIR/index
) and a flags argument (see above). Attempt to create a lockfile for the destination and return the file descriptor for writing to the file. - hold_lock_file_for_append
-
Like
hold_lock_file_for_update
, but before returning copy the existing contents of the file (if any) to the lockfile and position its write pointer at the end of the file. - fdopen_lock_file
-
Associate a stdio stream with the lockfile. Return NULL (without rolling back the lockfile) on error. The stream is closed automatically when
close_lock_file
is called or when the file is committed or rolled back. - get_locked_file_path
-
Return the path of the file that is locked by the specified lock_file object. The caller must free the memory.
- commit_lock_file
-
Take a pointer to the
struct lock_file
initialized with an earlier call tohold_lock_file_for_update
orhold_lock_file_for_append
, close the file descriptor, and rename the lockfile to its final destination. Return 0 upon success. On failure, roll back the lock file and return -1, witherrno
set to the value from the failing call toclose(2)
orrename(2)
. It is a bug to callcommit_lock_file
for alock_file
object that is not currently locked. - commit_lock_file_to
-
Like
commit_lock_file()
, except that it takes an explicitpath
argument to which the lockfile should be renamed. Thepath
must be on the same filesystem as the lock file. - rollback_lock_file
-
Take a pointer to the
struct lock_file
initialized with an earlier call tohold_lock_file_for_update
orhold_lock_file_for_append
, close the file descriptor and remove the lockfile. It is a NOOP to callrollback_lock_file()
for alock_file
object that has already been committed or rolled back. - close_lock_file
-
Take a pointer to the
struct lock_file
initialized with an earlier call tohold_lock_file_for_update
orhold_lock_file_for_append
. Close the file descriptor (and the file pointer if it has been opened usingfdopen_lock_file
). Return 0 upon success. On failure toclose(2)
, return a negative value and roll back the lock file. Usuallycommit_lock_file
,commit_lock_file_to
, orrollback_lock_file
should eventually be called ifclose_lock_file
succeeds. - reopen_lock_file
-
Re-open a lockfile that has been closed (using
close_lock_file
) but not yet committed or rolled back. This can be used to implement a sequence of operations like the following:-
Lock file.
-
Write new contents to lockfile, then
close_lock_file
to cause the contents to be written to disk. -
Pass the name of the lockfile to another program to allow it (and nobody else) to inspect the contents you wrote, while still holding the lock yourself.
-
reopen_lock_file
to reopen the lockfile. Make further updates to the contents. -
commit_lock_file
to make the final version permanent.
-