繁体   English   中英

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

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

支持我从一个提交创建多个分支(aaa、bbb、ccc)。 然后,我从其中一个分支 (bbb) 创建一个新分支 (ddd) 并对其进行提交。

然后我把所有东西都推到了遥控器上。 另一个人怎么知道新分支(ddd)来自哪个分支?

我做的 git 命令是:

git 分支aaa
git分支bbb
git分支ccc
git 分支ddd bbb
git 结帐ddd
回声 2 >> 文件
git 添加文件
git 提交 -m "2"

git 日志将显示


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

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

* 提交 dd24bb6 (master)

甚至有可能知道 ddd 是从 bbb 分支出来的?

谢谢

一般来说,这确实是不可能的。 Git 仅记录1引用名称(例如分支或标签)指向的单个提交 ID (SHA-1)。 提交的历史完全由该提交的父 ID 确定,不记录分支名称。 当您推送到远程时,您的“推送”操作会发送您正在推送的提交的 SHA-1(加上任何其他链接对象的更多 SHA-1——树和文件、父提交等——以及所有这些对象,根据需要根据遥控器上缺少的内容),并要求遥控器将分支设置为指向新的 SHA-1。

换句话说,你告诉遥控器:“这里,有提交 1234567,并设置分支 label ddd = 1234567”。 它可能会告诉您“要做到这一点,我需要五个其他提交”,其中一个您已标记为bbb ,但如果您不告诉远程“哦顺便将 label bbb设置为另一个提交”,那么它就赢了在任何地方都没有这些信息。


1这有点夸大其词:git 还在 reflog 中记录了存储在 label 中的每个 SHA-1,包括分支标签。 因此,可以回顾标签的历史以“找出它的起点”。 但这有两个限制: reflog 是纯本地的,从不通过 fetch 或 push 传输; 并且 reflogs 在这些情况下通常会在 90 天后过期(尽管这是可配置的,并且存在额外的复杂性)。 所以只要我们说有推动步骤,或者让3个多月过去,就没有办法说出来。

将这两个函数添加到 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
}

那么当你创建一个新分支时,不要运行git checkout -b mybranch而是运行:

newbranch mybranch

这会将您的分支日志存储在.git/branching_history文件中。 您可以使用以下命令检查日志:

branchinghistory

output 应该是:

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

分支只不过是指向特定提交的指针。 您只能看到ddd从哪个提交分支,而不是哪个分支。

分支只是指向提交的指针。 正因为如此,除了观察到两个分支在某个点上具有相同的历史之外,不可能看到一个分支的起源。

对于上游的人来说,分支的来源无关紧要,只是它包含某个提交(或提交序列)。 这决定了 git 如何/是否能够快进或合并分支。

Append 将此片段放入您的.bashrc.zshrc文件中。 通过执行以下操作注意 git 二进制文件的真实路径:

$ which git
/usr/local/bin/git

如果 git 具有不同的路径,请将其调整为以下代码段。

这样,您可以在创建分支并重新基于新分支时注册分支的历史记录:

# 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 "${@}"
}

因此,假设您从branchA创建了一个名为branchB的新分支:

(branchA) $ git checkout -b branchB

然后,你在branchC上 rebase 这个新分支,所以新的基础分支会改变:

(branchB) $ git rebase --onto branchC branchA

要知道当前branchB的基本分支,只需执行以下操作:

(branchB) $ git branch history

branchB created from branchA
branchB rebased onto branchC

感谢@kkarpieszuk 的想法

暂无
暂无

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

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