GIT - 如何知道一个分支是从哪个分支创建的?

20

如果我从一个提交创建多个分支(aaa、bbb、ccc),然后从其中一个分支(bbb)创建一个新分支(ddd),并在其上进行提交。然后,我将所有内容推送到远程仓库。另一个人如何知道新的分支(ddd)来自哪个分支?

我使用的git命令是:

git branch aaa
git branch bbb
git branch ccc
git branch ddd bbb
git checkout ddd
echo 2 >> file
git add file
git commit -m "2"

git日志会显示:


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

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

* commit dd24bb6 (master)

甚至可以知道ddd是从bbb分支派生出来的吗?

谢谢

6个回答

10

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

换句话说,您告诉远程:“在这里,拿取提交1234567,并将分支标签ddd = 1234567设定。”它可能会告诉您“要这样做,我需要5个其他提交”,其中一个您已经标记为bbb,但如果您不告诉远程“顺便也将标签bbb设置为这个其他提交”,那么它就不会在任何地方有这些信息。


这有点夸张:git还记录了reflog中存储在标签中的每个SHA-1,包括分支标签。因此,可以通过这个标签的历史回溯来“找出它从哪里开始”。但是,这有两个限制:reflogs仅在本地纪录,不会通过fetch或push传输;并且reflogs会过期,在这些情况下通常在90天后(尽管这是可配置的,并且存在额外的复杂性)。因此,只要我们说有一个推送步骤,或者允许超过3个月的时间,就无法判断。


非常感谢大家。这让我想到一个问题,我猜你们应该熟悉nvie的gitflow命令;当执行git flow feature finish <name>时,它会知道从哪个分支开始,并正确地将其合并回去。这是否意味着它只在本地工作?我对git命令包装器不太熟悉。再次感谢。 - Ng Khin Hooi
@NgKhinHooi:我没有使用过git flow,但它一定会使用一些侧面渠道(在配置文件中记录合并的“目标”,或者在另一个引用中隐藏在存储库中,或类似的方式)。 - torek

7

在你的 .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

输出应该是:

2020-04-22 23:59:06: 从主干创建了分支mybranch


我经常需要从功能 wip 分支创建新分支,有时会忘记是否已经这样做了。这个脚本会很有用。谢谢! - Isaac Pak
非常好的解决方案,还可以通过创建git别名来扩展。唯一罕见的问题可能是如果有人使用rebase onto,但这非常非常罕见! - Alessandro Argentieri

3

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


3

分支只是指向提交的指针。因此,除了观察两个分支在某个点上具有相同的历史记录外,无法看到分支的起源。

对于上游的某个人来说,分支的起源并不重要,只要它包含特定的提交(或一系列提交)。这确定git如何/是否能够将分支快进或合并在一起。


1
将以下代码添加到您的.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上进行变基,因此新的基础分支将会改变:

(branchB) $ git rebase --onto branchC branchA

要知道当前分支branchB的基础分支,请执行以下操作:
(branchB) $ git branch history

branchB created from branchA
branchB rebased onto branchC

感谢@kkarpieszuk提供的创意


0

你可以通过 git reflog 命令获取它。 如果你输入 git reflog 命令,你会发现类似于这样的内容。 enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接