ChatGPT解决这个技术问题 Extra ChatGPT

Git change branch when file of same name is present

I have in my git repo, a file named xyz. Coincidently, I also have a branch named xyz. Presently I am on master, but I want to checkout to branch xyz. The command to be used is simple

$ git checkout xyz

But this would checkout the file xyz to the present HEAD. How would I change my branch to branch xyz?


V
VonC

As illustrated by commit a047faf (git 1.8.4.3+), you can also try:

git checkout xyz --

(Note: the error message will be clearer with Git 2.21, Q1 2019)

That would make clear that the xyz part is a branch or commit, while everything after -- must be a path (here no path is provided). See more here on the double-hyphen convention.

If you try without the '--', that might or might not work, as shown in "Why does git checkout <remote_branchname> not create new tracking branch?":

git checkout name does: if it's local branch or explicit remote branch, switch to it. if it's a tracked path, reset it if it's a remote branch, create a tracking branch and switch to it.

And its behavior isn't always the same. Hence the '--' to provide a clear disambiguation.

Update August 2019, Git 2.23+

git checkout is too confusing and is replaced with:

git switch: meaning git switch xyz will work even if you have a file xyz,

git restore: meaning git restore xyz will work even if you have a branch xyz.

Plus, as I explain in "Why did my Git repo enter a detached HEAD state?", no more unexpected detached HEAD.


Better solution, IMO: stackoverflow.com/a/9537923/1096596
@BobbyA I have updated the answer with an even better answer
Why not git checkout -- docs? OpenGroup Guideline 10 talks about -- as the end of options argument, but I don't understand why it works at the end of that command, but not before docs.
@FernandoBasso In the answer, xyz is the name of a branch, not a path, hence the -- after xyz. But nowadays, you would not ask your self that question: using git switch (branch only) or git restore (path/file only) solve that. git checkout is obsolete and should not be used anymore.
M
Martin Tournoij

While VonC's solution works, I can never remember the syntax, so I typically use a more low-tech solution:

$ (cd somedir && git checkout my-branch)

Or, if you don't have any subdirectories:

$ (cd .git && git -C .. checkout my-branch)

It's easier to remember and it works ;-)


V
VonC

Git 2.21 (Q1 2019, 4+ years later) will clarify the error message and make suggestions

"git checkout frotz" (without any double-dash that I suggested initially) avoids ambiguity by making sure 'frotz' cannot be interpreted as a revision and as a path at the same time.

This safety has been updated to check also a unique remote-tracking branch 'frotz' in a remote, when dwimming to create a local branch 'frotz' out of a remote-tracking branch 'frotz' from a remote.

Note: "dwim" (used below) is "do what I mean", when a computer system attempts to anticipate what users intend to do, correcting trivial errors automatically rather than blindly executing users' explicit but potentially incorrect inputs.

See commit be4908f (13 Nov 2018) by Nguyễn Thái Ngọc Duy (pclouds).
(Merged by Junio C Hamano -- gitster -- in commit 8d7f9db, 04 Jan 2019)

checkout: disambiguate dwim tracking branches and local files

When checkout dwim is added in commit 70c9ac2, it is restricted to only dwim when certain conditions are met and fall back to default checkout behavior otherwise. It turns out falling back could be confusing. One of the conditions to turn git checkout frotz to git checkout -b frotz origin/frotz is that frotz must not exist as a file. But when the user comes to expect "git checkout frotz" to create the branch "frotz" and there happens to be a file named "frotz", git's silently reverting "frotz" file content is not helping. This is reported in Git mailing list and even used as an example of "Git is bad" elsewhere. We normally try to do the right thing, but when there are multiple "right things" to do, it's best to leave it to the user to decide. Check this case, ask the user to to disambiguate: "git checkout -- foo" will check out path "foo" "git checkout foo --" will dwim and create branch "foo" 6 For users who do not want dwim, use --no-guess. It's useless in this particular case because "git checkout --no-guess foo --" will just fail. But it could be used by scripts.

The man page for git checkout now includes:

--no-guess: Do not attempt to create a branch if a remote tracking branch of the same name exists.

Before Git 2.26 (Q1 2020), "git checkout X" did not correctly fail when X is not a local branch but could name more than one remote-tracking branches (i.e. to be dwimmed as the starting point to create a corresponding local branch), which has been corrected.

See commit fa74180, commit 2957709 (30 Dec 2019) by Alexandr Miloslavskiy (SyntevoAlex).
(Merged by Junio C Hamano -- gitster -- in commit d0e70cd, 05 Feb 2020)

checkout: don't revert file on ambiguous tracking branches Signed-off-by: Alexandr Miloslavskiy

For easier understanding, here are the existing good scenarios: Have no file 'foo', no local branch 'foo' and a single remote branch 'foo' git checkout foo will create local branch foo, see commit 70c9ac2 above, discussed here. and Have a file 'foo', no local branch 'foo' and a single remote branch 'foo' git checkout foo will complain, see commit be4908f above This patch prevents the following scenario: Have a file 'foo', no local branch 'foo' and multiple remote branches 'foo' git checkout foo will successfully... revert contents of file foo! That is, adding another remote suddenly changes behavior significantly, which is a surprise at best and could go unnoticed by user at worst. Please see commit be4908f above, which gives some real world complaints. To my understanding, fix in commit be4908f above (discussed here), overlooked the case of multiple remotes, and the whole behavior of falling back to reverting file was never intended: commit 70c9ac2 above introduces the unexpected behavior. Before, there was fallback from not-a-ref to pathspec. This is reasonable fallback. After, there is another fallback from ambiguous-remote to pathspec. I understand that it was a copy&paste oversight. commit ad8d510, from "Can't do a checkout with multiple remotes", and discussed here, noticed the unexpected behavior but chose to semi-document it instead of forbidding, because the goal of the patch series was focused on something else. commit be4908f above adds die() when there is ambiguity between branch and file. The case of multiple tracking branches is seemingly overlooked. The new behavior: if there is no local branch and multiple remote candidates, just die() and don't try reverting file whether it exists (prevents surprise) or not (improves error message).

With Git 2.30 (Q1 2021), "git checkout"(man) learned to use checkout.guess configuration variable and enable/disable its "--[no-]guess" option accordingly.

See commit 64f1f58 (07 Oct 2020), and commit ef09e7d (06 Oct 2020) by Denton Liu (Denton-L).
(Merged by Junio C Hamano -- gitster -- in commit 0e41cfa, 27 Oct 2020)

checkout: learn to respect checkout.guess Signed-off-by: Denton Liu

The current behavior of git checkout/switch is that --guess is currently enabled by default. However, some users may not wish for this to happen automatically. Instead of forcing users to specify --no-guess manually each time, teach these commands the checkout.guess configuration variable that gives users the option to set a default behavior. Teach the completion script to recognize the new config variable and disable DWIM logic if it is set to false.

git config now includes in its man page:

checkout.guess Provides the default value for the --guess or --no-guess option in git checkout and git switch. See git switch and git checkout.

git checkout now includes in its man page:

--guess is the default behavior. Use --no-guess to disable it. The default behavior can be set via the checkout.guess configuration variable.

git switch now includes in its man page:

The default behavior can be set via the checkout.guess configuration variable.


A
Alexey Ten

You're wrong. It will checkout branch xyz.

To checkout a file, you need to use command git checkout -- xyz. Git just allow you a shortcut for files if there is no branch with the same name.

See git checkout --help for details.


Why would I ask the question if it doesn't happen? I is happening to me. Generally on checking out a branch, the response is Switched to branch 'xyz', but in my case, there was no response. Which is the usual scenario when checking out a file. Also, I have seen the output of git branch -va to conclude that no such change has occurred.