查找Git分支创建时间(而非该分支的第一次提交时间)

15

如何知道 Git 分支是何时创建的?

我不想知道该分支的第一次提交是什么时候,我想找出该分支创建的时间。

这是一个用于重现工作示例的脚本:

#! /bin/bash
set -x
set -e

mkdir test
cd test
git init
echo "hello" >readme
git add readme
git commit -m "initial import"
date

sleep 5
git checkout -b br1
date                   # this is the date that I want to find out.

sleep 5
echo "hello_br1" >readme
git commit -a -m "hello_br1"
date

echo "hello_br1_b" >readme
git commit -a -m "hello_br1_b"

git checkout master
echo "hello_master" >readme
git commit -a -m "hello_master"

git branch -a; 
git log --all --graph --abbrev-commit --decorate --pretty=format:"%h - %an, %ad : %s" --date=iso

执行这个操作:

./test.sh 
++ set -e
++ mkdir test
++ cd test
++ git init
Initialized empty Git repository in /test_git/test2/.git/
++ echo hello
++ git add readme
++ git commit -m 'initial import'
[master (root-commit) 9b95944] initial import
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 readme
++ date
Fri Aug 16 17:51:24 CEST 2013
++ sleep 5
++ git checkout -b br1
Switched to a new branch 'br1'
++ date
Fri Aug 16 17:51:29 CEST 2013
++ sleep 5
++ echo hello_br1
++ git commit -a -m hello_br1
[br1 6c559cd] hello_br1
 1 files changed, 1 insertions(+), 1 deletions(-)
++ date
Fri Aug 16 17:51:34 CEST 2013
++ echo hello_br1_b
++ git commit -a -m hello_br1_b
[br1 5f0d8ab] hello_br1_b
 1 files changed, 1 insertions(+), 1 deletions(-)
++ git checkout master
Switched to branch 'master'
++ echo hello_master
++ git commit -a -m hello_master
[master 2ed092d] hello_master
 1 files changed, 1 insertions(+), 1 deletions(-)
++ git branch -a
  br1
* master
++ git log --all --graph --abbrev-commit --decorate '--pretty=format:%h - %an, %ad : %s' --date=iso
* 5f0d8ab - David Portabella, 2013-08-16 17:51:34 +0200 : hello_br1_b
* 6c559cd - David Portabella, 2013-08-16 17:51:34 +0200 : hello_br1
| * 2ed092d - David Portabella, 2013-08-16 17:51:34 +0200 : hello_master
|/  
* 9b95944 - David Portabella, 2013-08-16 17:51:24 +0200 : initial import

因此,使用git log或git reflog,我可以找到初始导入的日期(17:51:24)以及第一次提交到分支br1的日期(17:51:34)。

但是我需要查找分支br1创建的时间(17:51:29)。

如何做到这一点?

(奖励问题:它是否有哈希值?如何知道谁创建了该分支)


3个回答

37

抱歉,Git不会正式跟踪分支创建的信息(这不是存储和共享在存储库之间的数据)。分支只是对提交的引用,没有更多内容。这也意味着没有可以将您指向此数据的ID或对象。

reflog确实会跟踪分支进行更改的时间,但它仅是有限的历史记录,随着时间的推移而过期。它确实记录了一些信息。例如,“git branch bar”导致reflog中出现了这个条目:

:: git reflog show --date=iso bar
7d9b83d bar@{2013-08-16 12:23:28 -0400}: branch: Created from master

当我使用git checkout -b bar时,我也会看到类似的条目:

:: git co -b bar
Switched to a new branch 'bar'
:: git reflog show --date=iso bar
d6970ef bar@{2013-08-16 12:30:50 -0400}: branch: Created from HEAD

因此,根据您的使用情况和需要挖掘的历史深度,git reflog对您可能会有所帮助。


这个命令确实显示了我需要的信息(至少是日期),谢谢。很遗憾它没有正式地将此信息存储下来,永远保存。为什么它不会这样做呢?为什么有人决定不重要知道谁创建了一个分支以及何时创建的呢?不管怎样,你知道在远程仓库中如何实现相同的操作技巧吗?(当我想要找出谁在远程仓库中创建了一个分支时,这个技巧并没有起作用)。 - David Portabella
2
很不幸,我认为我们在远程库中没有相同的技巧。reflog 仅限于本地repo。在远程端,您可能会看到分支被创建,但作为推送的一部分,并且它将具有该时间戳(而不是作者创建它的时间戳)。至于为什么 Git 不跟踪它,最近在 git 邮件列表上进行了讨论,所以我不会再重复了。我会找出一个链接并稍后在此处发布(我现在必须走了)。简短版:他们认为保留这些内容不够有价值。 - John Szakmeister
git reflog show --date=iso branch-name 对我有用 - Vishal Kottarathil
对于那些感兴趣的人,我有一个脚本试图找到分支点:https://github.com/jszakmeister/etc/blob/master/git-addons/git-branch-point。你需要有一些想法从哪里分支,但它可以相当不错地定位你从哪个提交分支。再次说明,Git在这里并不完美,因为它不跟踪该数据。 :-) - John Szakmeister

10
您无法通过Git本身找出分支是由谁创建的,也无法知道分支创建的时间。
因为Git不跟踪分支的元数据。它并不关心谁创建了一个分支(通常你会从远程获取大量分支),因为分支只是指向提交的指针(refs)。
因此,一个分支也没有分支——实际上,Git ref只是您.git文件夹中包含对象哈希的纯文本文件(或者在符号引用的情况下,是它引用的其他引用的名称)。

0

正如其他答案所指出的那样,git不会跟踪分支引用第一次创建的提交。

有一段时间,我使用以下技巧来查找先前的分支点:

git rev-list --simplify-by-decoration -2 HEAD | tail -n 1

虽然这样可以返回当前分支上方的先前分支点,但不一定是你创建当前分支时的分支点。例如,我正在某个分支上进行工作,并且想要回到在当前分支中删除它之前的一些调试代码,因此我创建了一个分支,在我的工作分支上切换并继续工作...当我在那个工作分支上运行上面的代码时,它会返回调试代码的分支点。

我使用bash别名/函数来处理常见的git用例,并且我有用于创建和删除分支的函数。 我还有一个函数,允许我获取创建当前分支的分支点提交。这是我bash函数/别名的简化版本:

branchpointfun() {
  CURB=`git rev-parse --abbrev-ref HEAD`
  BRANCHPOINTVAR=BRANCHPOINT_OF_${CURB}
  # If a branchpoint variable exists for the current branch
  if [[ -v ${BRANCHPOINTVAR} ]]; then
    echo ${!BRANCHPOINTVAR}
  else
    git rev-list --simplify-by-decoration -2 HEAD | tail -n 1
  fi
}
alias branchpoint=branchpointfun

branchfun() {
  NAME="$@";
  if [ "$NAME" != "" ]; then
    # Record where this branchpoint started in order to do diffs and linting with it later
    CURCOMMIT=`git rev-parse HEAD`
    export declare BRANCHPOINT_OF_${NAME}=$CURCOMMIT
    echo "export BRANCHPOINT_OF_${NAME}=$CURCOMMIT" >> $VARSFILE
    # Now create the branch
    git checkout -b $NAME;
  fi
}
alias branch=branchfun

closefun() {
  CURB=`git rev-parse --abbrev-ref HEAD`;
  SELBR=`git branch --merged | grep -E "^  $@" | cut -d " " -f 3`;
  git branch -d $SELBR;
  BRANCHPOINTVAR=BRANCHPOINT_OF_${SELBR}
  # If a branchpoint variable exists for the branch being removed
  if [[ -v ${BRANCHPOINTVAR} ]]; then
    unset ${BRANCHPOINTVAR}
    grep -v "^${BRANCHPOINTVAR}=" $VARSFILE > $VARSFILE
  fi
}
alias close=closefun

每当我想要获取当前分支的分支点时,我只需输入命令branchpoint

我删除了很多与分支点问题无关的自定义代码,并且没有测试这个简化版本,所以如果我忽略了什么,它可能不能按照原样工作。请注意,我的bashrc会源化$VARSFILE,以便分支点在终端会话之间保持不变。

我使用分支点来通过git diff评估当前分支的进度,并且我使用它来对自从分支以来更改的文件进行超级检查。


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