Using gitconfig per branch

前端 未结 5 535
故里飘歌
故里飘歌 2020-12-10 18:01

Our company uses many customized opensource project. Whenever I contribute upstream branch I have change to use my personal email/name. Is there any way to have gitconfig pe

5条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-10 18:36

    Git config supports conditional includes, which would be a nice solution, but at present the only supported condition is the path of the repository. Branches or remotes are not suitable to be conditions. When we make a commit, the local head doesn't have to point to a branch (detached HEAD state), and a local branch doesn't have to have a tracking branch. Besides, the name of a local branch doesn't have to match with the name of its tracking branch.

    The first possible solution I think of is post-commit. After a commit is done, in post-commit get the proper name and email and then run git -c user.name foo -c user.email bar commit --amend --no-edit to rewrite the commit with the name and email. After several tries, I find out that it results in an infinitive loop. A commit invokes post-commit to run another git commit.

    Then I try exporting variables like GIT_AUTHOR_NAME related with the name and email of the author and committer in pre-commit. It fails too. I think these values have to be passed at the very beginning of git commit and the first invoked pre-commit is already too late, not to mention prepare-commit-msg, commit-msg or post-commit that are invoked later.

    The third try is an alias like git $(foo) commit where foo returns the proper -c user.name=xx -c user.email=yy according to the branch name and its remote. But git alias involving a bash script is a mud pit and I just give it up.

    Finally I turn back to post-commit:

    #!/bin/bash
    
    head=`git rev-parse --abbrev-ref HEAD`
    remote=`git config --get branch."${head}".remote`
    if [ "$remote" = "origin" ];then
        git filter-branch -f --env-filter '
            export GIT_AUTHOR_NAME=xx \
            export GIT_AUTHOR_EMAIL=xx@foo.com \
            export GIT_COMMITTER_NAME=xx \
            export GIT_COMMITTER_EMAIL=xx@foo.com' \
            HEAD^..HEAD
    elif [ "$remote" = "gerrit" ];then
        git filter-branch -f --env-filter '
            export GIT_AUTHOR_NAME=yy \
            export GIT_AUTHOR_EMAIL=yy@bar.com \
            export GIT_COMMITTER_NAME=yy \
            export GIT_COMMITTER_EMAIL=yy@bar.com' \
            HEAD^..HEAD
    else
        echo no amend
    fi
    

    It works to some degree. But bugs are obvious. One of them is that, after git cherry-pick a commit whose author is someone else, the author name and email will become yours after git filter-branch is done. Besides, as mentioned in the first paragraph, if you want branches and remotes to be conditions like in this hook, then you must follow some strict flows. No detached HEAD, no absence of branch..remote in the config.

    I think the ideal solution could be an alias or a function. This answer also gives a nice hint. To balance the level of automation and convenience and robustness, it would be better to have two alias for two cases, like git -c user.name=foo user.email=foo@com commit. You decide which alias to use on different branches.

提交回复
热议问题