Hi Anders, responding here instead of to the cover letter (because there is none ;-)): great work! Others pointed out the really tiny nit that some phrases should start with lower-case, which would be nice to see addressed. I did not find any major issue anymore (apart from the slightly iffy assumption that `buf->ref` starts with `refs/heads/` and therefore `buf->ref + strlen("refs/heads/")` would not overrun, but I _think_ the current code enforces that prefix somewhere along the lines), so: Acked-by: Johannes Schindelin Thank you for this contribution! Dscho On Tue, 9 Nov 2021, Anders Kaseorg wrote: > Refuse to fetch into the currently checked out branch of any working > tree, not just the current one. > > Fixes this previously reported bug: > > https://public-inbox.org/git/cb957174-5e9a-5603-ea9e-ac9b58a2eaad@mathema.de > > As a side effect of using find_shared_symref, we’ll also refuse the > fetch when we’re on a detached HEAD because we’re rebasing or bisecting > on the branch in question. This seems like a sensible change. > > Signed-off-by: Anders Kaseorg > --- > builtin/fetch.c | 29 +++++++++++++++-------------- > t/t5516-fetch-push.sh | 18 ++++++++++++++++++ > 2 files changed, 33 insertions(+), 14 deletions(-) > > diff --git a/builtin/fetch.c b/builtin/fetch.c > index f7abbc31ff..ed8a906717 100644 > --- a/builtin/fetch.c > +++ b/builtin/fetch.c > @@ -28,6 +28,7 @@ > #include "promisor-remote.h" > #include "commit-graph.h" > #include "shallow.h" > +#include "worktree.h" > > #define FORCED_UPDATES_DELAY_WARNING_IN_MS (10 * 1000) > > @@ -854,7 +855,7 @@ static int update_local_ref(struct ref *ref, > int summary_width) > { > struct commit *current = NULL, *updated; > - struct branch *current_branch = branch_get(NULL); > + const struct worktree *wt; > const char *pretty_ref = prettify_refname(ref->name); > int fast_forward = 0; > > @@ -868,16 +869,18 @@ static int update_local_ref(struct ref *ref, > return 0; > } > > - if (current_branch && > - !strcmp(ref->name, current_branch->name) && > - !(update_head_ok || is_bare_repository()) && > + if (!update_head_ok && > + (wt = find_shared_symref("HEAD", ref->name)) && > + !wt->is_bare && > !is_null_oid(&ref->old_oid)) { > /* > * If this is the head, and it's not okay to update > * the head, and the old value of the head isn't empty... > */ > format_display(display, '!', _("[rejected]"), > - _("can't fetch in current branch"), > + wt->is_current ? > + _("can't fetch in current branch") : > + _("checked out in another worktree"), > remote, pretty_ref, summary_width); > return 1; > } > @@ -1387,16 +1390,14 @@ static int prune_refs(struct refspec *rs, struct ref *ref_map, > > static void check_not_current_branch(struct ref *ref_map) > { > - struct branch *current_branch = branch_get(NULL); > - > - if (is_bare_repository() || !current_branch) > - return; > - > + const struct worktree *wt; > for (; ref_map; ref_map = ref_map->next) > - if (ref_map->peer_ref && !strcmp(current_branch->refname, > - ref_map->peer_ref->name)) > - die(_("Refusing to fetch into current branch %s " > - "of non-bare repository"), current_branch->refname); > + if (ref_map->peer_ref && > + (wt = find_shared_symref("HEAD", ref_map->peer_ref->name)) && > + !wt->is_bare) > + die(_("Refusing to fetch into branch '%s' " > + "checked out at '%s'"), > + ref_map->peer_ref->name, wt->path); > } > > static int truncate_fetch_head(void) > diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh > index 8212ca56dc..f07e32126f 100755 > --- a/t/t5516-fetch-push.sh > +++ b/t/t5516-fetch-push.sh > @@ -1771,4 +1771,22 @@ test_expect_success 'denyCurrentBranch and worktrees' ' > git -C cloned push origin HEAD:new-wt && > test_must_fail git -C cloned push --delete origin new-wt > ' > + > +test_expect_success 'refuse fetch to current branch of worktree' ' > + test_when_finished "git worktree remove --force wt && git branch -D wt" && > + git worktree add wt && > + test_commit apple && > + test_must_fail git fetch . HEAD:wt && > + git fetch -u . HEAD:wt > +' > + > +test_expect_success 'refuse fetch to current branch of bare repository worktree' ' > + test_when_finished "rm -fr bare.git" && > + git clone --bare . bare.git && > + git -C bare.git worktree add wt && > + test_commit banana && > + test_must_fail git -C bare.git fetch .. HEAD:wt && > + git -C bare.git fetch -u .. HEAD:wt > +' > + > test_done > -- > 2.33.1 > >