branch -m: update all per-worktree HEADs
When renaming a branch, currently only the HEAD of current working tree is updated, but it must update HEADs of all working trees which point at the old branch. This is the current behavior, /path/to/wt's HEAD is not updated: % git worktree list /path/to 2c3c5f2 [master] /path/to/wt 2c3c5f2 [oldname] % git branch -m master master2 % git worktree list /path/to 2c3c5f2 [master2] /path/to/wt 2c3c5f2 [oldname] % git branch -m oldname newname % git worktree list /path/to 2c3c5f2 [master2] /path/to/wt 0000000 [oldname] This patch fixes this issue by updating all relevant worktree HEADs when renaming a branch. Signed-off-by: Kazuki Yamaguchi <k@rhe.jp> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									2233066e77
								
							
						
					
					
						commit
						70999e9cec
					
				
							
								
								
									
										23
									
								
								branch.c
								
								
								
								
							
							
						
						
									
										23
									
								
								branch.c
								
								
								
								
							|  | @ -344,3 +344,26 @@ void die_if_checked_out(const char *branch) | |||
| 		die(_("'%s' is already checked out at '%s'"), branch, existing); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int replace_each_worktree_head_symref(const char *oldref, const char *newref) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 	struct worktree **worktrees = get_worktrees(); | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; worktrees[i]; i++) { | ||||
| 		if (worktrees[i]->is_detached) | ||||
| 			continue; | ||||
| 		if (strcmp(oldref, worktrees[i]->head_ref)) | ||||
| 			continue; | ||||
|  | ||||
| 		if (set_worktree_head_symref(worktrees[i]->git_dir, newref)) { | ||||
| 			ret = -1; | ||||
| 			error(_("HEAD of working tree %s is not updated"), | ||||
| 			      worktrees[i]->path); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	free_worktrees(worktrees); | ||||
| 	return ret; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										7
									
								
								branch.h
								
								
								
								
							
							
						
						
									
										7
									
								
								branch.h
								
								
								
								
							|  | @ -60,4 +60,11 @@ extern int read_branch_desc(struct strbuf *, const char *branch_name); | |||
|  */ | ||||
| extern void die_if_checked_out(const char *branch); | ||||
|  | ||||
| /* | ||||
|  * Update all per-worktree HEADs pointing at the old ref to point the new ref. | ||||
|  * This will be used when renaming a branch. Returns 0 if successful, non-zero | ||||
|  * otherwise. | ||||
|  */ | ||||
| extern int replace_each_worktree_head_symref(const char *oldref, const char *newref); | ||||
|  | ||||
| #endif | ||||
|  |  | |||
|  | @ -552,8 +552,7 @@ static void rename_branch(const char *oldname, const char *newname, int force) | |||
| 	if (recovery) | ||||
| 		warning(_("Renamed a misnamed branch '%s' away"), oldref.buf + 11); | ||||
|  | ||||
| 	/* no need to pass logmsg here as HEAD didn't really move */ | ||||
| 	if (!strcmp(oldname, head) && create_symref("HEAD", newref.buf, NULL)) | ||||
| 	if (replace_each_worktree_head_symref(oldref.buf, newref.buf)) | ||||
| 		die(_("Branch renamed to %s, but HEAD is not updated!"), newname); | ||||
|  | ||||
| 	strbuf_addf(&oldsection, "branch.%s", oldref.buf + 11); | ||||
|  |  | |||
|  | @ -126,7 +126,28 @@ test_expect_success 'git branch -M foo bar should fail when bar is checked out' | |||
| test_expect_success 'git branch -M baz bam should succeed when baz is checked out' ' | ||||
| 	git checkout -b baz && | ||||
| 	git branch bam && | ||||
| 	git branch -M baz bam | ||||
| 	git branch -M baz bam && | ||||
| 	test $(git rev-parse --abbrev-ref HEAD) = bam | ||||
| ' | ||||
|  | ||||
| test_expect_success 'git branch -M baz bam should succeed when baz is checked out as linked working tree' ' | ||||
| 	git checkout master && | ||||
| 	git worktree add -b baz bazdir && | ||||
| 	git worktree add -f bazdir2 baz && | ||||
| 	git branch -M baz bam && | ||||
| 	test $(git -C bazdir rev-parse --abbrev-ref HEAD) = bam && | ||||
| 	test $(git -C bazdir2 rev-parse --abbrev-ref HEAD) = bam | ||||
| ' | ||||
|  | ||||
| test_expect_success 'git branch -M baz bam should succeed within a worktree in which baz is checked out' ' | ||||
| 	git checkout -b baz && | ||||
| 	git worktree add -f bazdir3 baz && | ||||
| 	( | ||||
| 		cd bazdir3 && | ||||
| 		git branch -M baz bam && | ||||
| 		test $(git rev-parse --abbrev-ref HEAD) = bam | ||||
| 	) && | ||||
| 	test $(git rev-parse --abbrev-ref HEAD) = bam | ||||
| ' | ||||
|  | ||||
| test_expect_success 'git branch -M master should work when master is checked out' ' | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Kazuki Yamaguchi
						Kazuki Yamaguchi