How to find the nearest parent of a Git branch?

后端 未结 21 2151
野性不改
野性不改 2020-11-22 00:54

Let\'s say I have the following local repository with a commit tree like this:

master --> a
            \\
             \\
      develop c --> d
               


        
21条回答
  •  情书的邮戳
    2020-11-22 01:05

    A solution

    The solution based on git show-branch did not quite work for me (see below), so I've combined it with the one based on git log and ended up with this:

    git log --decorate --simplify-by-decoration --oneline \ # selects only commits with a branch or tag
          | grep -v "(HEAD" \                               # removes current head (and branch)
          | head -n1 \                                      # selects only the closest decoration
          | sed 's/.* (\(.*\)) .*/\1/' \                    # filters out everything but decorations
          | sed 's/\(.*\), .*/\1/' \                        # picks only the first decoration
          | sed 's/origin\///'                              # strips "origin/" from the decoration
    

    Limitations and Caveats

    • HEAD can be detached (many CI tools do so to ensure they build correct commit in a given branch), but origin branch and local branch have to be both at par or "above" the current HEAD.
    • There must be no tags in the way (I presume; I have not tested the script on commits with a tag between child and parent branch)
    • the script relies on the fact "HEAD" is always listed as the first decoration by the log command
    • running the script on master and develop results (mostly) in Initial commit

    The results

     A---B---D---E---F <-origin/master, master
          \      \
           \      \
            \      G---H---I <- origin/hotfix, hotfix
             \
              \
               J---K---L <-origin/develop, develop
                    \
                     \
                      M---N---O <-origin/feature/a, feature/a
                           \   \
                            \   \
                             \   P---Q---R <-origin/feature/b, feature/b
                              \
                               \
                                S---T---U <-origin/feature/c, feature/c
    

    Despite local branch existence (e.g. only origin/topic is present since the commit O was checked-out by directly by its SHA), the script should print as follows:

    • For commits G, H, I (branch hotfix) → master
    • For commits M, N, O (branch feature/a) → develop
    • For commits S, T, U (branch feature/c) → develop
    • For commits P, Q, R (branch feature/b) → feature/a
    • For commits J, K, L (branch develop) → Initial commit*
    • For commits B, D, E, F (branch master) → Initial commit

    * - or master if develop's commits were on top of master's HEAD (~ the master would be fast-forwardable to develop)


    Why did not show-branch work for me

    The solution based on git show-branch proved unreliable for me in the following situations:

    • detached HEAD – including detached head case means replacing grep '\*' \ for `grep '!' \ – and that is just the beginning of all the troubles
    • running the script on master and develop results in develop and `` respectively
    • branches on master branch (hotfix/ branches) end up with the develop as a parent since their closest master branch parent was marked with ! instead of * for a reason.

提交回复
热议问题