From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>,
"Marc Branchaud" <marcnarc@xiplink.com>
Subject: [PATCH v3 23/32] prune: strategies for linked checkouts
Date: Sun, 28 Sep 2014 08:22:37 +0700 [thread overview]
Message-ID: <1411867366-3821-24-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1411867366-3821-1-git-send-email-pclouds@gmail.com>
(alias R=$GIT_COMMON_DIR/worktrees/<id>)
- linked checkouts are supposed to keep its location in $R/gitdir up
to date. The use case is auto fixup after a manual checkout move.
- linked checkouts are supposed to update mtime of $R/gitdir. If
$R/gitdir's mtime is older than a limit, and it points to nowhere,
worktrees/<id> is to be pruned.
- If $R/locked exists, worktrees/<id> is not supposed to be pruned. If
$R/locked exists and $R/gitdir's mtime is older than a really long
limit, warn about old unused repo.
- "git checkout --to" is supposed to make a hard link named $R/link
pointing to the .git file on supported file systems to help detect
the user manually deleting the checkout. If $R/link exists and its
link count is greated than 1, the repo is kept.
Helped-by: Marc Branchaud <marcnarc@xiplink.com>
Helped-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Marc Branchaud <marcnarc@xiplink.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Documentation/git-checkout.txt | 20 +++++++
Documentation/git-prune.txt | 3 +
Documentation/gitrepository-layout.txt | 19 ++++++
builtin/checkout.c | 19 +++++-
builtin/prune.c | 95 ++++++++++++++++++++++++++++++
setup.c | 13 ++++
t/t2026-prune-linked-checkouts.sh (new +x) | 84 ++++++++++++++++++++++++++
7 files changed, 251 insertions(+), 2 deletions(-)
create mode 100755 t/t2026-prune-linked-checkouts.sh
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index c101575..35675da 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -434,6 +434,26 @@ thumb is do not make any assumption about whether a path belongs to
$GIT_DIR or $GIT_COMMON_DIR when you need to directly access something
inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path.
+When you are done with a linked working tree you can simply delete it.
+You can clean up any stale $GIT_DIR/worktrees entries via `git prune
+--worktrees` in the main or any linked working tree.
+
+If you move a linked working directory to another file system, or
+within a file system that does not support hard links, you need to run
+at least one git command inside the linked working directory
+(e.g. `git status`) in order to update its entry in $GIT_DIR/worktrees
+so that it does not get automatically removed.
+
+To prevent `git prune --worktrees` from deleting a $GIT_DIR/worktrees
+entry (which can be useful in some situations, such as when the
+entry's working tree is stored on a portable device), add a file named
+'locked' to the entry's directory. The file contains the reason in
+plain text. For example, if a linked working tree's `.git` file points
+to `/path/main/.git/worktrees/test-next` then a file named
+`/path/main/.git/worktrees/test-next/locked` will prevent the
+`test-next` entry from being pruned. See
+linkgit:gitrepository-layout[5] for details.
+
EXAMPLES
--------
diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt
index 7a493c8..1cf3bed 100644
--- a/Documentation/git-prune.txt
+++ b/Documentation/git-prune.txt
@@ -48,6 +48,9 @@ OPTIONS
--expire <time>::
Only expire loose objects older than <time>.
+--worktrees::
+ Prune dead working tree information in $GIT_DIR/worktrees.
+
<head>...::
In addition to objects
reachable from any of our references, keep objects
diff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt
index 8228450..2b30a92 100644
--- a/Documentation/gitrepository-layout.txt
+++ b/Documentation/gitrepository-layout.txt
@@ -259,6 +259,25 @@ worktrees::
$GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/worktrees" will be
used instead.
+worktrees/<id>/gitdir::
+ A text file containing the absolute path back to the .git file
+ that points to here. This is used to check if the linked
+ repository has been manually removed and there is no need to
+ keep this directory any more. mtime of this file should be
+ updated every time the linked repository is accessed.
+
+worktrees/<id>/locked::
+ If this file exists, the linked repository may be on a
+ portable device and not available. It does not mean that the
+ linked repository is gone and `worktrees/<id>` could be
+ removed. The file's content contains a reason string on why
+ the repository is locked.
+
+worktrees/<id>/link::
+ If this file exists, it is a hard link to the linked .git
+ file. It is used to detect if the linked repository is
+ manually removed.
+
SEE ALSO
--------
linkgit:git-init[1],
diff --git a/builtin/checkout.c b/builtin/checkout.c
index ad10f99..ab46af9 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -826,7 +826,7 @@ static int prepare_linked_checkout(const struct checkout_opts *opts,
const char *path = opts->new_worktree, *name;
struct stat st;
struct child_process cp;
- int counter = 0, len;
+ int counter = 0, len, ret;
if (!new->commit)
die(_("no branch specified"));
@@ -857,11 +857,21 @@ static int prepare_linked_checkout(const struct checkout_opts *opts,
if (mkdir(sb_repo.buf, 0777))
die_errno(_("could not create directory of '%s'"), sb_repo.buf);
+ /*
+ * lock the incomplete repo so prune won't delete it, unlock
+ * after the preparation is over.
+ */
+ strbuf_addf(&sb, "%s/locked", sb_repo.buf);
+ write_file(sb.buf, 1, "initializing\n");
+
strbuf_addf(&sb_git, "%s/.git", path);
if (safe_create_leading_directories_const(sb_git.buf))
die_errno(_("could not create leading directories of '%s'"),
sb_git.buf);
+ strbuf_reset(&sb);
+ strbuf_addf(&sb, "%s/gitdir", sb_repo.buf);
+ write_file(sb.buf, 1, "%s\n", real_path(sb_git.buf));
write_file(sb_git.buf, 1, "gitdir: %s/worktrees/%s\n",
real_path(get_git_common_dir()), name);
/*
@@ -870,6 +880,7 @@ static int prepare_linked_checkout(const struct checkout_opts *opts,
* value would do because this value will be ignored and
* replaced at the next (real) checkout.
*/
+ strbuf_reset(&sb);
strbuf_addf(&sb, "%s/HEAD", sb_repo.buf);
write_file(sb.buf, 1, "%s\n", sha1_to_hex(new->commit->object.sha1));
strbuf_reset(&sb);
@@ -885,7 +896,11 @@ static int prepare_linked_checkout(const struct checkout_opts *opts,
memset(&cp, 0, sizeof(cp));
cp.git_cmd = 1;
cp.argv = opts->saved_argv;
- return run_command(&cp);
+ ret = run_command(&cp);
+ strbuf_reset(&sb);
+ strbuf_addf(&sb, "%s/locked", sb_repo.buf);
+ unlink_or_warn(sb.buf);
+ return ret;
}
static int git_checkout_config(const char *var, const char *value, void *cb)
diff --git a/builtin/prune.c b/builtin/prune.c
index 144a3bd..cf56110 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -112,6 +112,91 @@ static void prune_object_dir(const char *path)
}
}
+static int prune_worktree(const char *id, struct strbuf *reason)
+{
+ struct stat st;
+ char *path;
+ int fd, len;
+
+ if (!is_directory(git_path("worktrees/%s", id))) {
+ strbuf_addf(reason, _("Removing worktrees/%s: not a valid directory"), id);
+ return 1;
+ }
+ if (file_exists(git_path("worktrees/%s/locked", id)))
+ return 0;
+ if (stat(git_path("worktrees/%s/gitdir", id), &st)) {
+ strbuf_addf(reason, _("Removing worktrees/%s: gitdir file does not exist"), id);
+ return 1;
+ }
+ fd = open(git_path("worktrees/%s/gitdir", id), O_RDONLY);
+ if (fd < 0) {
+ strbuf_addf(reason, _("Removing worktrees/%s: unable to read gitdir file (%s)"),
+ id, strerror(errno));
+ return 1;
+ }
+ len = st.st_size;
+ path = xmalloc(len + 1);
+ read_in_full(fd, path, len);
+ close(fd);
+ while (len && (path[len - 1] == '\n' || path[len - 1] == '\r'))
+ len--;
+ if (!len) {
+ strbuf_addf(reason, _("Removing worktrees/%s: invalid gitdir file"), id);
+ free(path);
+ return 1;
+ }
+ path[len] = '\0';
+ if (!file_exists(path)) {
+ struct stat st_link;
+ free(path);
+ /*
+ * the repo is moved manually and has not been
+ * accessed since?
+ */
+ if (!stat(git_path("worktrees/%s/link", id), &st_link) &&
+ st_link.st_nlink > 1)
+ return 0;
+ strbuf_addf(reason, _("Removing worktrees/%s: gitdir file points to non-existent location"), id);
+ return 1;
+ }
+ free(path);
+ return st.st_mtime <= expire;
+}
+
+static void prune_worktrees(void)
+{
+ struct strbuf reason = STRBUF_INIT;
+ struct strbuf path = STRBUF_INIT;
+ DIR *dir = opendir(git_path("worktrees"));
+ struct dirent *d;
+ int ret;
+ if (!dir)
+ return;
+ while ((d = readdir(dir)) != NULL) {
+ if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+ continue;
+ strbuf_reset(&reason);
+ if (!prune_worktree(d->d_name, &reason))
+ continue;
+ if (show_only || verbose)
+ printf("%s\n", reason.buf);
+ if (show_only)
+ continue;
+ strbuf_reset(&path);
+ strbuf_addstr(&path, git_path("worktrees/%s", d->d_name));
+ ret = remove_dir_recursively(&path, 0);
+ if (ret < 0 && errno == ENOTDIR)
+ ret = unlink(path.buf);
+ if (ret)
+ error(_("failed to remove: %s"), strerror(errno));
+ }
+ closedir(dir);
+ if (!show_only)
+ rmdir(git_path("worktrees"));
+ strbuf_release(&reason);
+ strbuf_release(&path);
+}
+
/*
* Write errors (particularly out of space) can result in
* failed temporary packs (and more rarely indexes and other
@@ -138,10 +223,12 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
{
struct rev_info revs;
struct progress *progress = NULL;
+ int do_prune_worktrees = 0;
const struct option options[] = {
OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
OPT__VERBOSE(&verbose, N_("report pruned objects")),
OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
+ OPT_BOOL(0, "worktrees", &do_prune_worktrees, N_("prune .git/worktrees")),
OPT_EXPIRY_DATE(0, "expire", &expire,
N_("expire objects older than <time>")),
OPT_END()
@@ -154,6 +241,14 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
init_revisions(&revs, prefix);
argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
+
+ if (do_prune_worktrees) {
+ if (argc)
+ die(_("--worktrees does not take extra arguments"));
+ prune_worktrees();
+ return 0;
+ }
+
while (argc--) {
unsigned char sha1[20];
const char *name = *argv++;
diff --git a/setup.c b/setup.c
index b99bdd3..fb61860 100644
--- a/setup.c
+++ b/setup.c
@@ -390,6 +390,17 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
return ret;
}
+static void update_linked_gitdir(const char *gitfile, const char *gitdir)
+{
+ struct strbuf path = STRBUF_INIT;
+ struct stat st;
+
+ strbuf_addf(&path, "%s/gitfile", gitdir);
+ if (stat(path.buf, &st) || st.st_mtime + 24 * 3600 < time(NULL))
+ write_file(path.buf, 0, "%s\n", gitfile);
+ strbuf_release(&path);
+}
+
/*
* Try to read the location of the git directory from the .git file,
* return path to git directory if found.
@@ -438,6 +449,8 @@ const char *read_gitfile(const char *path)
if (!is_git_directory(dir))
die("Not a git repository: %s", dir);
+
+ update_linked_gitdir(path, dir);
path = real_path(dir);
free(buf);
diff --git a/t/t2026-prune-linked-checkouts.sh b/t/t2026-prune-linked-checkouts.sh
new file mode 100755
index 0000000..3622800
--- /dev/null
+++ b/t/t2026-prune-linked-checkouts.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+test_description='prune $GIT_DIR/worktrees'
+
+. ./test-lib.sh
+
+test_expect_success 'prune --worktrees on normal repo' '
+ git prune --worktrees &&
+ test_must_fail git prune --worktrees abc
+'
+
+test_expect_success 'prune files inside $GIT_DIR/worktrees' '
+ mkdir .git/worktrees &&
+ : >.git/worktrees/abc &&
+ git prune --worktrees --verbose >actual &&
+ cat >expect <<EOF &&
+Removing worktrees/abc: not a valid directory
+EOF
+ test_i18ncmp expect actual &&
+ ! test -f .git/worktrees/abc &&
+ ! test -d .git/worktrees
+'
+
+test_expect_success 'prune directories without gitdir' '
+ mkdir -p .git/worktrees/def/abc &&
+ : >.git/worktrees/def/def &&
+ cat >expect <<EOF &&
+Removing worktrees/def: gitdir file does not exist
+EOF
+ git prune --worktrees --verbose >actual &&
+ test_i18ncmp expect actual &&
+ ! test -d .git/worktrees/def &&
+ ! test -d .git/worktrees
+'
+
+test_expect_success POSIXPERM 'prune directories with unreadable gitdir' '
+ mkdir -p .git/worktrees/def/abc &&
+ : >.git/worktrees/def/def &&
+ : >.git/worktrees/def/gitdir &&
+ chmod u-r .git/worktrees/def/gitdir &&
+ git prune --worktrees --verbose >actual &&
+ test_i18ngrep "Removing worktrees/def: unable to read gitdir file" actual &&
+ ! test -d .git/worktrees/def &&
+ ! test -d .git/worktrees
+'
+
+test_expect_success 'prune directories with invalid gitdir' '
+ mkdir -p .git/worktrees/def/abc &&
+ : >.git/worktrees/def/def &&
+ : >.git/worktrees/def/gitdir &&
+ git prune --worktrees --verbose >actual &&
+ test_i18ngrep "Removing worktrees/def: invalid gitdir file" actual &&
+ ! test -d .git/worktrees/def &&
+ ! test -d .git/worktrees
+'
+
+test_expect_success 'prune directories with gitdir pointing to nowhere' '
+ mkdir -p .git/worktrees/def/abc &&
+ : >.git/worktrees/def/def &&
+ echo "$TRASH_DIRECTORY"/nowhere >.git/worktrees/def/gitdir &&
+ git prune --worktrees --verbose >actual &&
+ test_i18ngrep "Removing worktrees/def: gitdir file points to non-existent location" actual &&
+ ! test -d .git/worktrees/def &&
+ ! test -d .git/worktrees
+'
+
+test_expect_success 'not prune locked checkout' '
+ test_when_finished rm -r .git/worktrees
+ mkdir -p .git/worktrees/ghi &&
+ : >.git/worktrees/ghi/locked &&
+ git prune --worktrees &&
+ test -d .git/worktrees/ghi
+'
+
+test_expect_success 'not prune recent checkouts' '
+ test_when_finished rm -r .git/worktrees
+ mkdir zz &&
+ mkdir -p .git/worktrees/jlm &&
+ echo "$TRASH_DIRECTORY"/zz >.git/worktrees/jlm/gitdir &&
+ git prune --worktrees --verbose --expire=2.days.ago &&
+ test -d .git/worktrees/jlm
+'
+
+test_done
--
2.1.0.rc0.78.gc0d8480
next prev parent reply other threads:[~2014-09-28 1:25 UTC|newest]
Thread overview: 134+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-30 8:33 [PATCH 00/32] nd/multiple-work-trees cleanup Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 01/32] path.c: make get_pathname() return strbuf instead of static buffer Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 02/32] path.c: make get_pathname() call sites return const char * Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 03/32] git_snpath(): retire and replace with strbuf_git_path() Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 04/32] path.c: rename vsnpath() to do_git_path() Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 05/32] path.c: group git_path(), git_pathdup() and strbuf_git_path() together Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 06/32] git_path(): be aware of file relocation in $GIT_DIR Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 07/32] *.sh: respect $GIT_INDEX_FILE Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 08/32] reflog: avoid constructing .lock path with git_path Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 09/32] fast-import: use git_path() for accessing .git dir instead of get_git_dir() Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 10/32] commit: use SEQ_DIR instead of hardcoding "sequencer" Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 11/32] $GIT_COMMON_DIR: a new environment variable Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 12/32] git-sh-setup.sh: use rev-parse --git-path to get $GIT_DIR/objects Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 13/32] *.sh: avoid hardcoding $GIT_DIR/hooks/ Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 14/32] git-stash: avoid hardcoding $GIT_DIR/logs/ Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 15/32] setup.c: convert is_git_directory() to use strbuf Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 16/32] setup.c: detect $GIT_COMMON_DIR in is_git_directory() Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 17/32] setup.c: convert check_repository_format_gently to use strbuf Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 18/32] setup.c: detect $GIT_COMMON_DIR check_repository_format_gently() Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 19/32] setup.c: support multi-checkout repo setup Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 20/32] wrapper.c: wrapper to open a file, fprintf then close Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 21/32] use new wrapper write_file() for simple file writing Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 22/32] checkout: support checking out into a new working directory Nguyễn Thái Ngọc Duy
2014-08-30 20:50 ` Philip Oakley
2014-08-31 4:49 ` Duy Nguyen
2014-08-31 4:52 ` Duy Nguyen
2014-08-31 11:08 ` Philip Oakley
2014-09-02 12:27 ` Duy Nguyen
2014-09-02 14:51 ` Marc Branchaud
2014-09-02 17:33 ` Junio C Hamano
2014-09-04 14:19 ` Duy Nguyen
2014-09-08 10:52 ` Duy Nguyen
2014-09-08 14:06 ` Marc Branchaud
2014-09-05 3:26 ` Scott Schmit
2014-09-05 13:42 ` Duy Nguyen
2014-08-30 8:33 ` [PATCH 23/32] checkout: clean up half-prepared directories in --to mode Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 24/32] checkout: reject if the branch is already checked out elsewhere Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 25/32] prune: strategies for linked checkouts Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 26/32] gc: style change -- no SP before closing parenthesis Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 27/32] gc: factor out gc.pruneexpire parsing code Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 28/32] gc: support prune --repos Nguyễn Thái Ngọc Duy
2014-08-30 8:33 ` [PATCH 29/32] count-objects: report unused files in $GIT_DIR/repos/ Nguyễn Thái Ngọc Duy
2014-08-30 8:34 ` [PATCH 30/32] git_path(): keep "info/sparse-checkout" per work-tree Nguyễn Thái Ngọc Duy
2014-08-30 8:34 ` [PATCH 31/32] checkout: don't require a work tree when checking out into a new one Nguyễn Thái Ngọc Duy
2014-08-30 8:34 ` [PATCH 32/32] t2025: add a test to make sure grafts is working from a linked checkout Nguyễn Thái Ngọc Duy
2014-08-30 11:11 ` [PATCH 00/32] nd/multiple-work-trees cleanup Eric Sunshine
2014-08-30 11:14 ` Duy Nguyen
2014-09-02 17:29 ` Junio C Hamano
2014-09-10 22:41 ` [PATCH v2 00/32] nd/multiple-work-trees Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 01/32] path.c: make get_pathname() return strbuf instead of static buffer Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 02/32] path.c: make get_pathname() call sites return const char * Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 03/32] git_snpath(): retire and replace with strbuf_git_path() Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 04/32] path.c: rename vsnpath() to do_git_path() Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 05/32] path.c: group git_path(), git_pathdup() and strbuf_git_path() together Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 06/32] git_path(): be aware of file relocation in $GIT_DIR Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 07/32] *.sh: respect $GIT_INDEX_FILE Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 08/32] reflog: avoid constructing .lock path with git_path Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 09/32] fast-import: use git_path() for accessing .git dir instead of get_git_dir() Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 10/32] commit: use SEQ_DIR instead of hardcoding "sequencer" Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 11/32] $GIT_COMMON_DIR: a new environment variable Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 12/32] git-sh-setup.sh: use rev-parse --git-path to get $GIT_DIR/objects Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 13/32] *.sh: avoid hardcoding $GIT_DIR/hooks/ Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 14/32] git-stash: avoid hardcoding $GIT_DIR/logs/ Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 15/32] setup.c: convert is_git_directory() to use strbuf Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 16/32] setup.c: detect $GIT_COMMON_DIR in is_git_directory() Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 17/32] setup.c: convert check_repository_format_gently to use strbuf Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 18/32] setup.c: detect $GIT_COMMON_DIR check_repository_format_gently() Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 19/32] setup.c: support multi-checkout repo setup Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 20/32] wrapper.c: wrapper to open a file, fprintf then close Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 21/32] use new wrapper write_file() for simple file writing Nguyễn Thái Ngọc Duy
2014-09-10 22:41 ` [PATCH v2 22/32] checkout: support checking out into a new working directory Nguyễn Thái Ngọc Duy
2014-09-11 15:02 ` Marc Branchaud
2014-09-21 2:41 ` Duy Nguyen
2014-09-21 3:10 ` Eric Sunshine
2014-09-21 9:50 ` Duy Nguyen
2014-09-22 21:00 ` Marc Branchaud
2014-09-22 23:01 ` Eric Sunshine
2014-09-10 22:41 ` [PATCH v2 23/32] prune: strategies for linked checkouts Nguyễn Thái Ngọc Duy
2014-09-11 15:36 ` Marc Branchaud
2014-09-12 3:06 ` Eric Sunshine
2014-09-12 19:08 ` Marc Branchaud
2014-09-21 2:54 ` Duy Nguyen
2014-09-21 3:01 ` Eric Sunshine
2014-09-21 10:29 ` Duy Nguyen
2014-09-22 21:06 ` Marc Branchaud
2014-09-22 22:19 ` Eric Sunshine
2014-09-10 22:42 ` [PATCH v2 24/32] checkout: reject if the branch is already checked out elsewhere Nguyễn Thái Ngọc Duy
2014-09-10 22:42 ` [PATCH v2 25/32] checkout: clean up half-prepared directories in --to mode Nguyễn Thái Ngọc Duy
2014-09-10 22:42 ` [PATCH v2 26/32] gc: style change -- no SP before closing parenthesis Nguyễn Thái Ngọc Duy
2014-09-10 22:42 ` [PATCH v2 27/32] gc: factor out gc.pruneexpire parsing code Nguyễn Thái Ngọc Duy
2014-09-10 22:42 ` [PATCH v2 28/32] gc: support prune --worktrees Nguyễn Thái Ngọc Duy
2014-09-21 10:43 ` Duy Nguyen
2014-09-22 21:06 ` Marc Branchaud
2014-09-10 22:42 ` [PATCH v2 29/32] count-objects: report unused files in $GIT_DIR/worktrees/ Nguyễn Thái Ngọc Duy
2014-09-10 22:42 ` [PATCH v2 30/32] git_path(): keep "info/sparse-checkout" per work-tree Nguyễn Thái Ngọc Duy
2014-09-10 22:42 ` [PATCH v2 31/32] checkout: don't require a work tree when checking out into a new one Nguyễn Thái Ngọc Duy
2014-09-10 22:42 ` [PATCH v2 32/32] t2025: add a test to make sure grafts is working from a linked checkout Nguyễn Thái Ngọc Duy
2014-09-25 21:20 ` [PATCH v2 00/32] nd/multiple-work-trees Junio C Hamano
2014-09-28 1:22 ` [PATCH v3 " Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 01/32] path.c: make get_pathname() return strbuf instead of static buffer Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 02/32] path.c: make get_pathname() call sites return const char * Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 03/32] git_snpath(): retire and replace with strbuf_git_path() Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 04/32] path.c: rename vsnpath() to do_git_path() Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 05/32] path.c: group git_path(), git_pathdup() and strbuf_git_path() together Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 06/32] git_path(): be aware of file relocation in $GIT_DIR Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 07/32] *.sh: respect $GIT_INDEX_FILE Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 08/32] reflog: avoid constructing .lock path with git_path Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 09/32] fast-import: use git_path() for accessing .git dir instead of get_git_dir() Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 10/32] commit: use SEQ_DIR instead of hardcoding "sequencer" Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 11/32] $GIT_COMMON_DIR: a new environment variable Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 12/32] git-sh-setup.sh: use rev-parse --git-path to get $GIT_DIR/objects Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 13/32] *.sh: avoid hardcoding $GIT_DIR/hooks/ Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 14/32] git-stash: avoid hardcoding $GIT_DIR/logs/ Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 15/32] setup.c: convert is_git_directory() to use strbuf Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 16/32] setup.c: detect $GIT_COMMON_DIR in is_git_directory() Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 17/32] setup.c: convert check_repository_format_gently to use strbuf Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 18/32] setup.c: detect $GIT_COMMON_DIR check_repository_format_gently() Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 19/32] setup.c: support multi-checkout repo setup Nguyễn Thái Ngọc Duy
2014-10-01 16:19 ` Johannes Sixt
2014-09-28 1:22 ` [PATCH v3 20/32] wrapper.c: wrapper to open a file, fprintf then close Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 21/32] use new wrapper write_file() for simple file writing Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 22/32] checkout: support checking out into a new working directory Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` Nguyễn Thái Ngọc Duy [this message]
2014-10-01 16:20 ` [PATCH v3 23/32] prune: strategies for linked checkouts Johannes Sixt
2014-09-28 1:22 ` [PATCH v3 24/32] checkout: reject if the branch is already checked out elsewhere Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 25/32] checkout: clean up half-prepared directories in --to mode Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 26/32] gc: style change -- no SP before closing parenthesis Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 27/32] gc: factor out gc.pruneexpire parsing code Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 28/32] gc: support prune --worktrees Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 29/32] count-objects: report unused files in $GIT_DIR/worktrees/ Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 30/32] git_path(): keep "info/sparse-checkout" per work-tree Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 31/32] checkout: don't require a work tree when checking out into a new one Nguyễn Thái Ngọc Duy
2014-09-28 1:22 ` [PATCH v3 32/32] t2025: add a test to make sure grafts is working from a linked checkout Nguyễn Thái Ngọc Duy
2014-09-28 6:35 ` [PATCH v3 00/32] nd/multiple-work-trees Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1411867366-3821-24-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=marcnarc@xiplink.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).