git:看起来不像分支的分支

大阪Webbie

我从来没有掌握过git的窍门,而只从事断断续续的编程工作,所以我忘记了项目的状态。目前,我不了解git告诉我的有关旧分支的信息。

git branch -a 说:

  dashboard
* master
  php7
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/php7

因此它说除了master,我还有两个分支:dashboardphp7php7清楚地记得-这是许多提交工作的很大一部分。我不记得了dashboard,但是这个名字告诉我它与哪个文件有关。

git branch --merged 说:

  dashboard
* master
  php7

因此,显然两者都合并了。但是php7远程dashboard却不是。我不记得我为达到这一点做了什么git命令。

当我查看PHPStorm(或带有git log --graph中的日志时,这两个与我期望的分支看起来不一样-上面没有提交。这是日志的最新部分:在此处输入图片说明

谜团(至少对我来说):

  • 我记得在php7分支上做的承诺和都在同一条橙色线上master如果我合并然后删除了分支(逻辑分支),为什么它仍仍列为分支?
  • 为什么在php7分支的最后一个额外的“来源”标签我认为最近的推送将使远程看起来像本地,在最新提交上仅带有一个“原始”标签。当然,远程不认为php7还没有合并-这将是可怕的,因为该代码很关键。
  • dashboard根本不为人所知(https://github.com/OsakaWebbie/kizunadb)-怎么可能?

另一方面,在日志的前面,有一个非常明显的分支,该分支有两次提交,然后被合并,但不在分支列表中:在此处输入图片说明我很乐意将其删除(我不会保留旧的分支以留恋),但git branch -d texlabels表示:error: branch 'texlabels' not found.日志中看起来最分支的东西不是分支吗?我头疼。

我相信您git gurus会立即知道这一切的含义以及如何清理它-我期待您的澄清。

更新:

Thanks to Kata for a thorough answer (very likely to be accepted). But I have a few followup questions that would be hard to read in a tiny comment (I wish comments could be longer and have more formatting), so bear with me a little longer. I guess they can be answered either by a comment or by Kata adding to his answer - whatever works.

Because it is not sure that in the past php7 was merged into master.

If it's not sure that php7 was merged, why is it listed in --merged? (The thought of git being "unsure" about anything worries me...) I have no idea how to move a branch head later, so that scenario is unlikely. However, there was a time when I did something locally that caused Github to refuse pushes (I think I might have amended files to an already-pushed commit) - someone else helped me look it over, and I ended up doing push -f (I'm the only developer). Perhaps that caused a pointer to get out of place...

Anyway, I know the php7 code is part of my current codebase, because it is happily running on PHP7 now. And I recognize several of the commits as having been done on that branch. In fact, it's possible that all the commits from the time I created php7 until I merged it (46 commits) were done on that branch (i.e. no flipping back to master to fix bugs in the meantime). Would that explain why there is no extra line in the DAG beside the master line?

If so, then perhaps texlabels is the only branch I ever interrupted to fix a bug on master, since it's the only extra line in the DAG. Also, no other branch has an entry for "Merge branch 'so-and-so'" - is it because without any master commits, merge doesn't need to change any content (just move pointers)?

Because dashboard was created locally and has never pushed to remote.

Oh, I didn't realize that a basic push doesn't include branch information. Apparently Github knows about php7 because I no doubt did pushes while it was checked out. (Is that right?)

I've also now learned about tags, and I created a tag at the point I deployed my project on a new server with PHP7 and other differences. I would be happy to not have the php7 or dashboard branches anymore, as long as my current codebase stays my current codebase. But if you're saying that there is some uncertainty about their merge status, is it safe to delete them? (Deleting things sounds scary, but if it's merely a pointer...)

Update #2:

After Kata mentioned that without --all I might not be seeing everything, I did a diff between with/without that flag. I discovered that at the very beginning of my php7 work, the first four commits were repeated, first on a "branchy-looking" branch (only seen in --all), and then on the main line with everything else. Here is the relevant snippet from git log --graph --decorate --all --oneline:

* 3b1c25a Removal of .html files (won't work with the new server config) and $client in db connect file
* dccc3f3 minor edits
* 20a1aab remove .idea files from repo
* 629d891 Second day of cleanup for PHP7: various things, hacking away at errors one at a time (note: I
* a669fa0 First day of cleanup for PHP7:   * mysql_ to mysqli_ (major functions, anyway)   * convert my
| * 51738d1 (refs/original/refs/heads/php7) minor edits
| * f1aa0f9 remove .idea files from repo
| * 38aef9b (refs/original/refs/remotes/origin/php7) Second day of cleanup for PHP7: various things, ha
| * cfcaa51 First day of cleanup for PHP7:   * mysql_ to mysqli_ (major functions, anyway)   * convert
|/
* 294ef21 Feature: batch category delete

I'm guessing that the weirdness was somehow caused by me accidentally using the command line on my VM to do two of the four ("remove .idea..." & "minor edits") instead of OsakaWebbie like the rest of them. (The user doesn't show in --oneline, but you can see that on Github.) But no matter how it happened, I'm assuming the first set (cfcaa51 thru 51738d1) will go away when I delete the branch, but since they are repeated (and I know my current codebase reflects the changes in those commits), it should be okay, right?

Nghia Bui

You're better to think branches as heads (or pointers). What git log shows you is a DAG of the commits and a list of heads pointing to particular commits. What you can see at the current moment is something like: the php7 head is pointing to this commit. You cannot know in the past how the php7 head was moving since git allows us to move heads in a free manner.

Regarding git branch --merged [<commit>], look into its document, the command simply shows all the heads that can be reached from the <commit>. In your case, the <commit> is HEAD which means master. So the result is obvious: dashboard, master, and php7 are reachable from HEAD. Notice that by default git branch does not show remote heads, add -a option for that.

Now I think your questions could be answered.

Commits I remember doing on the php7 branch are all on the same orange line as master. If I merged and then deleted the branch (logical), why is it still listed as a branch at all?

Because it is not sure that in the past php7 was merged into master. Even if it was, it could be always that at some point later the php7 head was moved, so we cannot see the vestige of the merge caused by php7.

Why is there an extra "origin" label on the last of the php7 branch? I would think recent pushes would cause remote to look just like local, with only one "origin" label on the latest commit. Surely remote doesn't consider php7 to be not-yet-merged - that would be horrible, as that code is critical.

That label simply means that currently there are 2 heads -- php7 and origin/php7 -- pointing to that commit.

dashboard is not known by remote at all (https://github.com/OsakaWebbie/kizunadb) - how could that be?

Because dashboard was created locally and has never been pushed to remote.

I would be happy to delete it (I don't keep old branches for nostalgia), but git branch -d texlabels says: error: branch 'texlabels' not found. The most branchy-looking thing in the log isn't a branch? My head hurts.

You know the existing of the texlabels head just because you see its name in the commit message. But actually that head was deleted in the past thus at the moment you cannot delete it again.

Update:

To answer some more concerns of @OsakaWebbie

The --merged option is named based on the fact that, in normal development (i.e., you don't abnormally move heads, with git reset for example), if a head child can reach to a head parent, it means that parent was merged into child at some point in the past. In other words, child does inherit parent.

----------------------- child
         /
        /
     parent

But I empathise with you about this, actually there are complaints about the naming of git commands and their options.

Back to the story of your php7 head, I think the situation should be clear now.

A merge does not necessarily cause two paths joining into one. Indeed, as you told, since you switched to php7 and appended 46 commits to it, you hadn't appended any commit to master, so the history before the merge looks like this:

----------------- master
                    \
                     ----------------- php7

Then you switched back to master and made the merge: git merge php7. Because php7 is a child of master, the result of the merge should be exactly php7. Thus, git will simply move master forward and point it to the commit being pointed by php7. This kind of merge is called fast-forward. Then you have:

-------------------
                    \
                     ----------------- php7, master

which essentially is:

-------------------------------------- php7, master

But fast-forward did not happen with the merge of texlabels head. You created the head, switched to it, coded something and appended some commits. Then you switched back to master, also coded something and appended some commits. So you have:

----------------- master
     \
      ----------- texlabels

As you see texlabels is not a child of master. Hence this cannot be a fast-forward, merging texlabels into master will cause:

----------------- (old master) -- master
     \                         /
      ----------- texlabels

That's why it is the only branchy-looking thing in the history.

Regarding your two last concerns:

Oh, I didn't realize that a basic push doesn't include branch information. Apparently Github knows about php7 because I no doubt did pushes while it was checked out. (Is that right?)

git push <remote> [<head>] only pushes the provided <head> (and its ancestor commits of course). If <head> is not provided, then the head that is being pointed by HEAD will be used -- it is php7 in your case. To push all the heads, use --all option.

But if you're saying that there is some uncertainty about their merge status, is it safe to delete them? (Deleting things sounds scary, but if it's merely a pointer...)

Yes, heads are merely pointers, but please be careful: after deleting a head, some commits may be abandoned -- i.e., they cannot be reached from any head -- and will be cleaned (deleted) by the GC of git. If you are sure about what you are deleting, go ahead.


Some more notes:

  1. The push -f is not related here, it causes unexpected things in the remote (e.g., losing some commits), not in the local.
  2. By default git log shows only the commits that can be reached from HEAD, use --all option to show all commits.

Update #2:

About the 4 extra commits

It's very likely that at the commit 51738d1 minor edits you issued a git filter-branch command to massively modify something about those 4 commits (modify author names -- I guess). Then you had 4 new commits created (from a669fa0 to 3b1c25a). The 4 old commits (from cfcaa51 to 51738d1) are still there because they are still reachable from the heads refs/original/.... These heads were created by the backing-up mechanism of git filter-branch.

您完全可以删除这4个额外的提交它们与4个“主要”提交完全无关。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

尝试将本地分支链接到远程Heroku应用程序时,“ git <refspec>看起来不像ref”

当我执行git branch -a时,分支的分支看起来如何?

Android Studio - 工作目录中看起来像“git 分支”的“灰色 git 矩形”是什么?

git-将分支还原为看起来像master?

Django:看起来不像模块路径

CSV文件看起来不像表格

Spring Security-编码密码看起来不像BCrypt

foreach看起来不像在php中正常工作

BCryptPasswordEncoder-编码的密码看起来不像BCrypt

编码的密码看起来并不像BCrypt

警告:编码的密码看起来不像BCrypt

Capistrano错误tar:这看起来不像tar存档

Ubuntu:这看起来不像tar存档

我如何制作看起来不像按钮的Glyphicon按钮

为什么firebase查询看起来不像列表?

焦油通过管道卷曲:看起来不像焦油档案

如何使迭代器类看起来不像容器类?

Django:m看起来不像模块路径

如何让我的菜单按钮看起来不像链接?

Java Spring Security 5 + MySQL数据库:编码后的密码看起来不像BCrypt

是否可以在Mac Pro上构建Electron Apps?由于怪异的GPU问题,看起来不像

无业游民的触发器并不像看起来那样简单

在SpringBoot 2.1.4中,编码后的密码看起来不像BCrypt.RELEASE

Android 应用程序图标看起来不像它应该的样子

Spring boot 和 jwt 编码的密码看起来不像 BCrypt

Tkinter中的ASCII艺术在控制台中看起来不像

CSS线性渐变看起来不像Photoshop,可以固定吗?

bz2文件和“这看起来不像tar存档”

从Series.axes返回的列表看起来不像普通列表