简体   繁体   English

GIT - 如何知道分支的分支?

[英]GIT - How to know the branch a branch branched from?

Support I create multiple branches (aaa, bbb, ccc) from a commit.支持我从一个提交创建多个分支(aaa、bbb、ccc)。 Then, I create a new branch (ddd) from one of the branch (bbb) and a make a commit on it.然后,我从其中一个分支 (bbb) 创建一个新分支 (ddd) 并对其进行提交。

Then I pushed everything to a remote.然后我把所有东西都推到了遥控器上。 How would another person knows the new branch (ddd) comes from which branch?另一个人怎么知道新分支(ddd)来自哪个分支?

The git commands I did was:我做的 git 命令是:

git branch aaa git 分支aaa
git branch bbb git分支bbb
git branch ccc git分支ccc
git branch ddd bbb git 分支ddd bbb
git checkout ddd git 结帐ddd
echo 2 >> file回声 2 >> 文件
git add file git 添加文件
git commit -m "2" git 提交 -m "2"

And the git log would show git 日志将显示


* commit d259a3b (HEAD, ddd) * 提交 d259a3b (HEAD, ddd)
| |
| | 2 2
| |

* commit efb038c (develop, ccc, bbb, aaa) * 提交 efb038c (develop, ccc, bbb, aaa)
| |
| | 1 1
| |

* commit dd24bb6 (master) * 提交 dd24bb6 (master)

It is even possible to know that ddd was branched from bbb?甚至有可能知道 ddd 是从 bbb 分支出来的?

Thanks谢谢

It is indeed impossible in general.一般来说,这确实是不可能的。 Git records only 1 the single commit-ID (SHA-1) to which a reference name (such as a branch or tag) points. Git 仅记录1引用名称(例如分支或标签)指向的单个提交 ID (SHA-1)。 The history of that commit is determined solely by that commit's parent IDs, which do not record branch-names.提交的历史完全由该提交的父 ID 确定,不记录分支名称。 When you push to a remote, your "push" operation sends the SHA-1 of the commit you're pushing (plus more SHA-1s for any other linked objects—trees and files, parent commits, etc—plus the contents of all those objects, as needed based on what's missing on the remote), and asks the remote to set its branch to point to the new SHA-1.当您推送到远程时,您的“推送”操作会发送您正在推送的提交的 SHA-1(加上任何其他链接对象的更多 SHA-1——树和文件、父提交等——以及所有这些对象,根据需要根据遥控器上缺少的内容),并要求遥控器将分支设置为指向新的 SHA-1。

In other words, you tell the remote: "here, have commit 1234567, and set branch label ddd = 1234567".换句话说,你告诉遥控器:“这里,有提交 1234567,并设置分支 label ddd = 1234567”。 It may tell you "to do that I need five other commits", one of which you have labeled as bbb , but if you don't tell the remote "oh by the way set label bbb to this other commit too" then it won't have that information anywhere.它可能会告诉您“要做到这一点,我需要五个其他提交”,其中一个您已标记为bbb ,但如果您不告诉远程“哦顺便将 label bbb设置为另一个提交”,那么它就赢了在任何地方都没有这些信息。


1 This is a bit of an overstatement: git also records, in the reflog, each SHA-1 that is stored in a label, including branch labels. 1这有点夸大其词:git 还在 reflog 中记录了存储在 label 中的每个 SHA-1,包括分支标签。 It is therefore possible to walk back through the label's history to "figure out where it started".因此,可以回顾标签的历史以“找出它的起点”。 There are two limits on this though: reflogs are purely local, never transmitted by fetch or push;但这有两个限制: reflog 是纯本地的,从不通过 fetch 或 push 传输; and reflogs expire, generally after 90 days in these cases (although this is configurable and there are additional complexities).并且 reflogs 在这些情况下通常会在 90 天后过期(尽管这是可配置的,并且存在额外的复杂性)。 So as long as we say there's a push step, or allow more than 3 months to pass, there's no way to tell.所以只要我们说有推动步骤,或者让3个多月过去,就没有办法说出来。

add those two functions to your.bashrc:将这两个函数添加到 your.bashrc:

function newbranch() {
    history_file=".git/branching_history"
    from=`git rev-parse --abbrev-ref HEAD`
    to=$1
    git checkout -b $1 > /dev/null 2>&1
    DATE=`date '+%Y-%m-%d %H:%M:%S'`
    echo "$DATE: from $from created branch $1" >> $history_file
}

function branchinghistory() {
    cat .git/branching_history
}

then when you create a new branch, don't run git checkout -b mybranch but do:那么当你创建一个新分支时,不要运行git checkout -b mybranch而是运行:

newbranch mybranch

this will store your branching log in .git/branching_history file.这会将您的分支日志存储在.git/branching_history文件中。 You can check the log with:您可以使用以下命令检查日志:

branchinghistory

the output should be: output 应该是:

2020-04-22 23:59:06: from master created branch mybranch

Branches are nothing more than pointers to a specific commit.分支只不过是指向特定提交的指针。 You can only see from which commit ddd was branched from, not which branch.您只能看到ddd从哪个提交分支,而不是哪个分支。

Branches are simply pointers to commits.分支只是指向提交的指针。 Because of this, it is not possible to see where a branch originated from, other than observing that two branches have an identical history up to some point.正因为如此,除了观察到两个分支在某个点上具有相同的历史之外,不可能看到一个分支的起源。

For someone upstream, it is not relevant where a branch originated from, only that it contains a certain commit (or sequence of commits).对于上游的人来说,分支的来源无关紧要,只是它包含某个提交(或提交序列)。 This determines how/if git is able to fast-forward or merge branches together.这决定了 git 如何/是否能够快进或合并分支。

Append this snippet into your .bashrc or .zshrc files. Append 将此片段放入您的.bashrc.zshrc文件中。 Pay attention to the real path of your git binary by doing:通过执行以下操作注意 git 二进制文件的真实路径:

$ which git
/usr/local/bin/git

If git has a different path, adapt it into the following snippet.如果 git 具有不同的路径,请将其调整为以下代码段。

This way you can register the history of a branch when it is created and rebased onto a new branch:这样,您可以在创建分支并重新基于新分支时注册分支的历史记录:

# keeps track of the branch from which a new branch is created.
# it updates the history of the branch in case of rebase onto
# when the branch is deleted it deletes its history also
# es. (branchA) $ git checkout -b branchB
#     (branchB) $ git branch --onto branchC branchA 
#     (branchB) $ git branch history
#     branchB created from branchA
#     branchB rebased onto branchC
git() {

   if [ "${1}" == "checkout" ] && [ "${2}" == "-b" ]; then
      mkdir -p .git/branches_history
      if [ "${4}" != "" ]; then
        # git checkout -b <new-branch> <from-branch>
        echo "${3} created from ${4}" > .git/branches_history/${3}
      else
        # git checkout -b <new-branch>
        echo "${3} created from $(/usr/local/bin/git branch --show-current)" > .git/branches_history/${3}
      fi
    
   elif [ "${1}" == "rebase" ] && [ "${2}" == "--onto" ]; then
      mkdir -p .git/branches_history
      if [ "${5}" != "" ]; then
         # git rebase --onto <new-base> <old-base> <branch-to-be-rebased>
         echo "${5} rebased onto ${3}" >> .git/branches_history/${5}
      else 
         # git rebase --onto <new-base> <old-base>
         echo "$(/usr/local/bin/git branch --show-current) rebased onto ${3}" >> .git/branches_history/$(/usr/local/bin/git branch --show-current)
      fi
      
   elif [ "${1}" == "branch" ]; then
       if [ "${2}" == "-d" ] || [ "${2}" == "-D" ] || [ "${2}" == "--delete" ] || [ "${2}" == "--force-delete" ]; then
          # git branch -d <branch> | git branch -D <branch>
          rm -rf .git/branches_history/${3} &> /dev/null
       elif [ "${2}" == "history" ]; then
             if [ "${3}" != "" ]; then 
                # git branch history <branch>
                branchName=${3}
             else
                # git branch history
                branchName=$(/usr/local/bin/git branch --show-current)
             fi
             cat .git/branches_history/${branchName}
             # return because git branch history is not a real git command, so git doesn't have to do anything
             return 0
       fi
   fi
   # perform the real git command
   /usr/local/bin/git "${@}"
}

So, imagine that from branchA you create a new branch named branchB :因此,假设您从branchA创建了一个名为branchB的新分支:

(branchA) $ git checkout -b branchB

Then, you rebase this new branch on branchC , so the new base branch will change:然后,你在branchC上 rebase 这个新分支,所以新的基础分支会改变:

(branchB) $ git rebase --onto branchC branchA

To know the base branch of the current branchB just do:要知道当前branchB的基本分支,只需执行以下操作:

(branchB) $ git branch history

branchB created from branchA
branchB rebased onto branchC

Thanks to @kkarpieszuk for the idea感谢@kkarpieszuk 的想法

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

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