git checkout感到困惑

use*_*276 4 git

我是git的新手,并试图围绕分支的工作方式.根据文档git checkout

更新工作树中的文件以匹配索引或指定树中的版本.如果>没有给出路径,git checkout也会更新HEAD以将指定的分支设置为>当前分支.

所以据我所知,我工作的目录中的文件(我执行git init的文件)应该根据我所在的分支进行更改.我很困惑,因为当我在分支之间切换时不会发生这种情况.在切换分支之前我正在编辑的编辑存在于我切换到的分支中.我做错了什么或git checkout不能这样工作,我只是误解了文档?

Von*_*onC 11

That confusion is acknowledged by Git 2.23.
Git 2.23 (Q3 2019) will replace git checkout with two new commands:

See commit 97ed685, commit d16dc42, commit bcba406 (20 Jun 2019), commit 4e43b7f, commit 1235875, commit 80f537f, commit fc991b4, commit 75f4c7c, commit 4df3ec6, commit 2f0896e, commit a5e5f39, commit 3a733ce, commit e3ddd3b, commit 183fb44, commit 4058199, commit a6cfb9b, commit be8ed50, commit c9c935f, commit 46e91b6 (25 Apr 2019), and commit 328c6cb (29 Mar 2019) by Nguy?n Thái Ng?c Duy (pclouds).
(Merged by Junio C Hamano -- gitster -- in commit f496b06, 09 Jul 2019)

checkout: split part of it to new command 'switch'

"git checkout" doing too many things is a source of confusion for many users (and it even bites old timers sometimes).
To remedy that, the command will be split into two new ones: switch and restore. The good old "git checkout" command is still here and will be until all (or most of users) are sick of it.

And:

switch: reject if some operation is in progress

Unless you know what you're doing, switching to another branch to do something then switching back could be confusing. Worse, you may even forget that you're in the middle of something. By the time you realize, you may have done a ton of work and it gets harder to go back.

A new option --ignore-in-progress was considered but dropped because it was not exactly clear what should happen.
Sometimes you can switch away and get back safely and resume the operation. Sometimes not.
And the git-checkout behavior is automatically clear merge/revert/cherry-pick, which makes it a bit even more confusing.
See this discussion.

We may revisit and add this option in the future.
But for now play it safe and not allow it (you can't even skip this check with --force).
The user is suggested to cancel the operation by themselves (and hopefully they do consider the consequences, not blindly type the command), or to create a separate worktree instead of switching.

The third option is the good old "git checkout", but it's not mentioned.


See git switch man page

DESCRIPTION

Switch to a specified branch.
The working tree and the index are updated to match the branch.
All new commits will be added to the tip of this branch.

Optionally a new branch could be created with either -c, -C, automatically from a remote branch of same name (see --guess), or detach the working tree from any branch with --detach, along with switching.

Switching branches does not require a clean index and working tree (i.e. no differences compared to HEAD).
The operation is aborted however if the operation leads to loss of local changes, unless told otherwise with --discard-changes or --merge.


EXAMPLES

The following command switches to the "master" branch:

$ git switch master
Run Code Online (Sandbox Code Playgroud)

After working in the wrong branch, switching to the correct branch would be done using:

$ git switch mytopic
Run Code Online (Sandbox Code Playgroud)

However, your "wrong" branch and correct "mytopic" branch may differ in files that you have modified locally, in which case the above switch would fail like this:

$ git switch mytopic
error: You have local changes to 'frotz'; not switching branches.
Run Code Online (Sandbox Code Playgroud)

You can give the -m flag to the command, which would try a three-way merge:

$ git switch -m mytopic
Auto-merging frotz
Run Code Online (Sandbox Code Playgroud)

After this three-way merge, the local modifications are not registered in your index file, so git diff would show you what changes you made since the tip of the new branch.

To switch back to the previous branch before we switched to mytopic (i.e. "master" branch):

$ git switch -
Run Code Online (Sandbox Code Playgroud)

You can grow a new branch from any commit.
For example, switch to "HEAD~3" and create branch "fixup":

$ git switch -c fixup HEAD~3
Switched to a new branch 'fixup'
Run Code Online (Sandbox Code Playgroud)

If you want to start a new branch from a remote branch of the same name:

$ git switch new-topic
Branch 'new-topic' set up to track remote branch 'new-topic' from 'origin'
Switched to a new branch 'new-topic'
Run Code Online (Sandbox Code Playgroud)

To check out commit HEAD~3 for temporary inspection or experiment without creating a new branch:

$ git switch --detach HEAD~3
HEAD is now at 9fc9555312 Merge branch 'cc/shared-index-permbits'
Run Code Online (Sandbox Code Playgroud)

If it turns out whatever you have done is worth keeping, you can always create a new name for it (without switching away):

$ git switch -c good-surprises
Run Code Online (Sandbox Code Playgroud)


tor*_*rek 7

Git有一个将一八个或十个不同的东西塞进一个命令的普遍问题.

git add 可以更新工作树,通常可以.

可以改变git checkout点,有时也可以,有时不改变.

如果要重置文件并撤消工作,它可以覆盖您对文件所做的工作.或者它可以拒绝覆盖您对文件所做的工作,在更改HEAD更改时保持不变HEAD.

关于这一切的事情是,尽管描述起来非常困难,但它实际上都是有意义的,过了一段时间你就习惯了这一点,并且发现一个命令在大多数情况下都符合你的意思.(当然,"大多数时候"可能是一个问题......)

无论如何,你所看到的特殊行为是一个刻意的特征.假设您从分支开始HEAD,就像大多数存储库那样:

$ git clone ...
$ git branch
* master
$
Run Code Online (Sandbox Code Playgroud)

此时你可能会编辑一些文件,进行一些工作,然后才意识到:"哇!我打算在分支上做这个master!" 1

git让你在这一点上做的是切换到(或创建)分支develop,保持你的修改,在一个条件下:切换到develop不需要擦除它们.假设您修改了文件develop并创建了一个新文件,f1现在您想要创建并签出f2应该从中开始的本地分支,并自动"跟踪",2 develop:

$ git checkout develop 
Run Code Online (Sandbox Code Playgroud)

(在非常古老的git版本中,你必须拼写这个origin/develop).

我们还要说git checkout -b develop --track origin/develop分支f1和分支的提示文件是一样的master.3 对于git来说,这意味着它可以执行此检出,因为它不必修改文件develop,因此它可以将现有更改保留f1在原位.

如果文件f1同样在这两个承诺,或(在这种情况下)在任何一个不存在,则没有文件会被打一顿,并且f2将创建新的本地分支git checkout,修改工作树相匹配develop的需要,而这不包括修改origin/develop,也不包括删除f1,所以你到目前为止所完成的工作仍然完好无损.

这允许您将新的更改提交到本地f2.

(如果碰上那里的git的情况下必须撤消更改,但还是要"移动"到另一个分支,惯用的伎俩是使用develop脚本.这听起来像一个简单的事情,git stash往往是使用简单,但它实际上是一个非常复杂的小动物.不过不要担心,直到你需要它.)


1这发生在我身上所有的时间.很多时候我想创建一个新的非跟踪分支,这比切换到现有分支要简单一些,但原则仍然适用.

2这种自动跟踪功能可让您更轻松地引入其他人所做的更改:一旦git选择了这些更改git stash,git会通知您其他人的更改,并让您使用git fetchgit merge将您的更改与他们的更改结合起来,而不是很多额外的戳 - 即将弄清楚谁的变化在哪里.

3既然你是git的新手,那么概念就像区分"分支的尖端"(这是一个特定的提交)和"分支",这实际上是模糊的 - 有分支标签,然后有分支结构由提交树 - 是你应该暂时忽略的其他东西.需要注意的主要事情是git存储库中有一个特殊的文件命名git rebase,在该特殊文件中,git会写入字符串,HEAD或者ref: refs/heads/master为了跟踪你所在的分支.所以ref: refs/heads/develop会写git checkout Xref: refs/heads/X一旦切换到分支HEAD.

同时,存储库中的另一组特殊文件告诉git该分支X指的是那些丑陋的SHA-1之一master.这是分支的"小费" c06f8d11b75e28328cdc809397eddd768ebeb533.当你进行新的提交时master,git会创建新提交"一个旧提示",然后将新的SHA-1写入分支文件,这样master现在就是你的新提交.

精确的细节并不重要,因为新的提交只是推进了分支.