简体   繁体   English

Git:为什么“git 分支”没有列出所有分支?

[英]Git: why doesn't "git branch" list all the branches?

I've previous experience with Mercurial and I'm having trouble understanding the Git branching.我以前有过使用 Mercurial 的经验,但我无法理解 Git 分支。 Why does the为什么

git branch

only list some of the branches and I need to run只列出一些分支,我需要运行

git branch -a

to get list of all branches?获取所有分支的列表? It seems to me that Git has multiple different branch types whereas Mercurial has only one.在我看来,Git 有多种不同的分支类型,而 Mercurial 只有一种。

As I wrote at https://stackoverflow.com/a/11223644/334451 it's actually the other way around.正如我在https://stackoverflow.com/a/11223644/334451所写的,实际上是相反的。 Mercurial has multiple things that are logically branches: unnamed branches , named branches and bookmarks . Mercurial 有多个逻辑分支:未命名分支命名分支书签 Git only has branches but it uses namespaces for branch names (basically namespace path for a branch + the name of branch). Git 只有分支,但它使用名称空间作为分支名称(基本上是分支的名称空间路径 + 分支名称)。 Git users often speak about " master " branch (or " main " nowadays) and you have to decipher from the context if they actually mean refs/heads/master or refs/remotes/origin/master or something else. Git 用户经常谈论“ master ”分支(或现在的“ main ”),如果它们实际上是指refs/heads/masterrefs/remotes/origin/master或其他东西,您必须从上下文中破译。 Git is also smart enough to guess the correct path if you use just the last part of the full name and in some context the interpretation of short names is explicitly defined. Git 也足够聪明,如果您只使用全名的最后一部分并且在某些上下文中明确定义了短名称的解释,则可以猜测正确的路径。 For example, when you say例如,当你说

git push origin foo:bar

it will actually execute (assuming foo is local branch and not a tag)它会实际执行(假设foo是本地分支而不是标签)

git push origin refs/heads/foo:refs/heads/bar

which means 'take the local " refs/heads/foo " and push it to remote server " origin " using name " refs/heads/bar " on the remote server'.这意味着“获取本地“ refs/heads/foo ”并使用远程服务器上的名称“ refs/heads/bar ”将其推送到远程服务器“ origin ”。 You can use commit SHA-1 for the source as long as the target is a branch that already exists (otherwise git cannot know if you want to create a new tag or branch).只要目标是已经存在的分支,您就可以对源使用提交 SHA-1(否则 git 无法知道您是否要创建新标签或分支)。 I prefer to use this syntax if I ever need to force (overwrite) things on the remote server so that I can accurately specify the new state of the target branch.如果我需要在远程服务器上强制(覆盖)某些东西,我更喜欢使用这种语法,以便我可以准确地指定目标分支的新 state。

As everything actually has full namespaced name (refname), you can also do stuff like having branch master (actually refs/heads/master ) and tag master (actually refs/tags/master ) but that's just asking for trouble.由于所有内容实际上都有完整的命名空间名称(refname),因此您还可以执行诸如拥有分支 master (实际上是refs/heads/master )和标记 master (实际上是refs/tags/master )之类的事情,但这只是自找麻烦。 Git always uses the full refnames under the hood but allows using shorter names in the user interface. Git 始终在后台使用完整的引用名称,但允许在用户界面中使用较短的名称。

By default, when you run " git branch " it lists only refs/heads/* without the full refname.默认情况下,当您运行“ git branch ”时,它仅列出refs/heads/*而没有完整的 refname。 For full branch names you have to run something like对于完整的分支名称,您必须运行类似

git branch --format="%(refname)"

or for all branches, local or remote no matter how many remote servers you've configured或者对于所有分支,本地或远程,无论您配置了多少远程服务器

git branch -a --format="%(refname)"

which will list full names of all the known branches.这将列出所有已知分支的全名。 All those names are actually file paths under the directory .git/refs/ in your working directory so the whole system is actually really simple (the file at the end of that path contains just the SHA-1 of the commit that's the tip of that branch).所有这些名称实际上都是工作目录中.git/refs/目录下的文件路径,因此整个系统实际上非常简单(该路径末尾的文件仅包含提交的 SHA-1分支)。 When you "create a new branch" in Git, you literally create one new file with 41 bytes containing the currently checked out commit SHA-1 (output of " git rev-parse HEAD ") with trailing linefeed and the name of the file is the name of the branch you created.当您在 Git 中“创建一个新分支”时,您实际上创建了一个 41 字节的新文件,其中包含当前签出的提交 SHA-1(“ git rev-parse HEAD ”的输出),带有尾随换行符,文件名是您创建的分支的名称。 The file .git/HEAD contains textual reference to currently checked out commit or head or tag in your working directory.文件.git/HEAD包含对当前已签出的提交或工作目录中的头或标记的文本引用。

Git also supports using branch names that contains slashes in which case there will be additional directory levels under the refs/heads/ hierarchy but everything else works just the same. Git 还支持使用包含斜杠的分支名称,在这种情况下,在refs/heads/层次结构下会有额外的目录级别,但其他一切都一样。 The official git repo for git uses branch names prefixed with extra directory levels. git 的官方 git 存储库使用带有额外目录级别前缀的分支名称。

Git tags are implemented similarly but those are stored in .git/refs/tags/ and will not be automatically modified when you create new commits after checking out a tag. Git 标签的实现方式类似,但它们存储在.git/refs/tags/中,并且在签出标签后创建新提交时不会自动修改。 Note that tags are not kept in separate namespaces but when you fetch changes, you automatically get all the tags, too, and those are always in the prefix refs/tags/ .请注意,标签不会保存在单独的命名空间中,但是当您获取更改时,您也会自动获取所有标签,并且这些标签始终位于前缀refs/tags/中。

You can list all known tags with full refnames using command您可以使用命令列出所有具有完整引用名的已知标签

git tag --format='%(refname)'

Note that " git tag -a " does exist but it doesn't mean "list all" but "create annotated tag" (a tag that has more info attached to it instead of just the name) because tags do not have namespaces, so there's no need for "list all tags".请注意,“ git tag -a ”确实存在,但它并不意味着“列出所有”而是“创建带注释的标签”(一个附加了更多信息而不仅仅是名称的标签),因为标签没有命名空间,所以不需要“列出所有标签”。

The branches starting with refs/remote/ will be updated automatically when you run " git fetch " (or do " git pull " which will run " git fetch " behind your back).当您运行“ git fetch ”(或执行“ git pull ”将运行“ git fetch ”)时,以refs/remote/开头的分支将自动更新。

Git will be much easier to understand if you never ever use " git pull " for anything.如果您从不使用“ git pull ”做任何事情,Git 将更容易理解。 Always run " git fetch " (or " git fetch --all " if you have multiple remote servers) instead and it will only update the refs/remote/ hierarchy only and download the required pack /object files to actually know what all those SHA-1's mean.始终运行“ git fetch ”(或“ git fetch --all ”,如果您有多个远程服务器),它只会更新refs/remote/层次结构并下载所需的pack /对象文件以实际了解所有这些 SHA -1 的意思。 After you have executed " git fetch " you can use " gitk --all ", " gitg " or some other repository viewer that can show both local and remote branches.执行“ git fetch ”后,您可以使用“ gitk --all ”、“ gitg ”或其他可以同时显示本地和远程分支的存储库查看器。 If you don't have any GUI tools, you can run something like如果你没有任何 GUI 工具,你可以运行类似的东西

git log --oneline --decorate --graph --all

or (everything on one line)或(一行中的所有内容)

git log --graph --all --pretty=format:"%C(auto)%h%d%Creset %s %Cgreen(%cr)%Creset"

Then you can sanely decide if you want to merge , rebase or do something else.然后,您可以明智地决定是否要mergerebase或做其他事情。

As a party trick, you can also do stuff like作为派对技巧,您还可以执行以下操作

git push . HEAD:foo

which means push to local repository, update local branch HEAD as the new value for branch " foo " (fast forward), where HEAD is currently checked out version as usual.这意味着推送到本地存储库,将本地分支HEAD更新为分支“ foo ”(快进)的新值,其中HEAD当前像往常一样被检出版本。 You can use SHA-1 here, too.您也可以在此处使用 SHA-1。 This is mostly helpful when you use feature branches and want to include your current feature branch to local " master " branch.当您使用功能分支并希望将当前功能分支包含到本地“ master ”分支时,这非常有用。 Instead of checking out master and "merging in" the changes from your feature branch, you can simply push current branch to local master branch.您可以简单地将当前分支推送到本地 master 分支,而不是从您的功能分支中检出 master 并“合并”更改。 This is better than forcing master branch to HEAD because Git will show an error if the change wouldn't be fast-forward.这比强制master分支到HEAD更好,因为如果更改不会快进,Git 将显示错误。 I have aliased " git update-master " to " git push. HEAD:master " just for this purpose.为了这个目的,我将“ git update-master ”别名为“ git push. HEAD:master ”。 (And I don't actually type git update-master but git ui followed by TAB which autocompletes the rest. Be sure to enable autocompletion for all git commands in your shell unless enabled by default.) (And I don't actually type git update-master but git ui followed by TAB which autocompletes the rest. Be sure to enable autocompletion for all git commands in your shell unless enabled by default.)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM