How to tell git branch name from commit hash?

前端 未结 4 1492
旧时难觅i
旧时难觅i 2021-02-19 01:52

I have a bash script which accepts a string of either a branch name (e.g., \"master\", or \"feature/foo\") or a commit hash (e.g. \"1234abcd\").

I have the repository c

相关标签:
4条回答
  • 2021-02-19 02:03

    If you would like a robust mechanism to tell relative names (e.g. you SHA1 is possibly one or so commits behind a named branch), you can use git name-rev to resolve it.

    Examples:

    $ git config remote.upstream.url
    https://github.com/RobotLocomotion/drake.git
    
    $ git log --oneline -n 5
    7530a95 Merge pull request #5743 from soonho-tri/pr-reformat-mathematical_program
    ebc8f25 Suppresses console output of speed_bump.obj genrule. (#5726)
    d8b9a0b Merge pull request #5735 from david-german-tri/namespaces
    79e10e8 Remove redundant 'symbolic::' prefix from mathematical_program code
    b68b590 Clean up mathematical_program code by adding using std::*
    
    $ git name-rev HEAD
    HEAD master
    $ git name-rev 79e10e8
    79e10e8 master^2
    $ git name-rev HEAD~20
    HEAD~20 remotes/origin/issue/5646_return_binding~3
    

    Reference: Git Tips (old commit)

    UPDATE: As @kporter mentioned, there is also the --name-only flag (with new commits as of 2020/04/21):

    $ git name-rev HEAD
    HEAD tags/last_sha_with_original_matlab~313
    $ git name-rev --name-only HEAD~20
    tags/last_sha_with_original_matlab~333
    

    Command-Line Reference: git name-rev

    0 讨论(0)
  • 2021-02-19 02:04

    You can use git show-ref:

    git show-ref --head | grep refs
    

    If it is empty, it is a SHA1 (or an invalid object, which isn't good).
    If not, it is a branch name.


    A better technique comes from "Validate if commit exists", using git merge-base:

    A branch name will result in a different string (the SHA1)

    C:\Users\vonc\prog\b2d>git merge-base master master
    de4accfd28c5f25fcc057d56996b83450be5dc60
    

    a SHA1 will result in the same result (or at least starts with the same result):

    C:\Users\vonc\prog\b2d>git merge-base 03949c3d3f88a378c6a08e57daa97059b52813f1 03949c3d3f88a378c6a08e57daa97059b52813f1
    03949c3d3f88a378c6a08e57daa97059b52813f1
    

    foobar will fail:

    C:\Users\vonc\prog\b2d>git merge-base xxx xxx
    fatal: Not a valid object name xxx
    

    That means something like:

    if [[ git merge-base $string $string ]]; then
      if [[ $(git merge-base $string $string) == $string* ]]; then
        echo "SHA1"
      else
        echo "branch"
      fi
    else
      echo "Not a valid object name '$string'"
    fi
    
    0 讨论(0)
  • 2021-02-19 02:07

    Imo you can't check this reliably, since a hash is also a valid branch name. Try:

    git checkout -b 0c8158f47d7dda89226d4e816fee1fb9ac6c1204
    

    This means there can be a situation where a branch with that name exists but also a commit.

    Since you can pass a branch name or a commit to most of the git commands, you don't need to differentiate between them.

    0 讨论(0)
  • 2021-02-19 02:21

    As @VonC and @hek2mgl mentioned, this may not be a one or the other test. You could slightly modify your script to something like this (borrowed from this SO answer:

    #!/bin/bash
    commit_or_branch="$1"
    cd /path/to/my_repo
    git fetch
    if git branch | grep $commit_or_branch 2> /dev/null
    then
        echo "it's a branch"
    fi
    
    if git cat-file -e $commit_or_branch 2> /dev/null
    then
      echo "it's a commit"
    fi
    

    Note that this only tests for local branches.. see this post if you're interested in remote branches.

    0 讨论(0)
提交回复
热议问题