2

So I needed to add my personal GitHub account to my office laptop in which I was already using my work github account. So I created a separate ssh key and stored that into a separate file. I added that newly created ssh to my personal github account.

Then I added a config file like this:

Work
   Host github.com
   HostName github.com
   User git
   IdentityFile ~/.ssh/id_rsa
   
 Personal account
   Host github.com-personal  
   HostName github.com
   User git
   IdentityFile ~/.ssh/id_rsa_personal

I then created a PRIVATE new repository in personal git repository and cloned it like the following so that it will use personal ssh token:

git clone git@github.com-personal:prajatpadhi/udemy-react-maximillian.git

I then made some commits and pushed. But I was surprised to see that the commit's author was my work's userid because I had forgotten to change the username and email of my local repository.

But shouldn't in such a case there should be an authorization error as the repository was private in the personal git hub account. How did GitHub allowed access?

My personal userid is lets say pp and work's pp1. How can pp1 be allowed to push a commit to pp's private repository?

Prajat Padhi
  • 89
  • 2
  • 9
  • 2
    This isn't to do with ssh, or its config. Check the repo's config. `git config --local --list`. `user.name` and `user.email` probably haven't been changed – evolutionxbox Jul 11 '22 at 16:50
  • Okay, let us assume that the config hasn't changed but shouldn't it restrict pushing a commit as the userid is of work and the repository is private in my personal account. – Prajat Padhi Jul 11 '22 at 16:52
  • 3
    `git commit` does not care about remotes at all. It just uses the configured git username and email to create the commits (which is the global default in your case). On the other hand `git push` does not care about commit authors, it will simply use the configured ssh key to authenticate. There is nothing stopping you from creating commits with arbitrary usernames and emails – perivesta Jul 11 '22 at 16:59
  • See https://stackoverflow.com/q/117006/7976758 , https://stackoverflow.com/q/8502123/7976758 and https://stackoverflow.com/q/28401926/7976758 – phd Jul 11 '22 at 18:11
  • 2
    The `user.name` and `user.email` settings are not *credentials*. The credentials are what you use to authenticate your computer and/or yourself to some other computer (e.g., the GitHub server) at `git push` time. Your basic options are either to restrict yourself on your end, or restrict yourself on GitHub's end. It may be too hard to do on GitHub's end, but you can use a simple pre-push hook on your own end to inspect the commits you're about to send. – torek Jul 11 '22 at 23:27
  • Thanks for all your response. I am more clear now on the git. Commit authors have nothing to do with authentication. – Prajat Padhi Jul 12 '22 at 19:00

2 Answers2

2

Here is a simple, but basically untested, pre-push hook that can check for commits made with user.name and/or user.email settings that you don't want. Modify the check() function as desired.

#! /bin/sh
#
# pre-push hook to check commits to be sent
#
# The check() function takes a commit hash ID and decides if it's OK
# (returns zero) or not (returns nonzero).
check() {
        local hash="$1" ret=0
        set -- $(git log --no-walk --pretty=format:"%an %ae" $hash | sed 's/ /-/g')
        case "$1" in
        my-name-ok) ;;
        my-name-bad) echo "oops, wrong author name on commit $hash"; ret=1;;
        *) echo "oops? unknown author name $1 on $hash"; ret=1;;
        esac
        case "$2" in
        my-email-ok@my-host-ok) ;;
        *) echo "oops? unknown email address $2 on $hash"; ret=1;;
        esac
        return $ret
}

# cheesy hack to get appropriate number of 0s, assumes we're
# on a branch that exists.
NULLHASH=$(git rev-parse HEAD | sed 's/./0/g')

# Use git rev-list to figure out which commits to check.
# We could get fancy and accumulate them and uniq-ize them,
# but probably no reason to bother.
TF=$(mktemp)
trap "rm -f \"$TF\"" 0 1 2 3 15
status=0
while read localref localhash remoteref remotehash; do
        if [ "$localhash" = $NULLHASH ]; then continue; fi # --delete
        if [ "$remotehash" = $NULLHASH ]; then
                # creating a new name on the remote, so we don't
                # know for sure what's new to them, but we'll just
                # assume that `--not --remotes` is good here (!!!)
                scancmd="git rev-list $localhash --not --remotes
        else
                scancmd="git rev-list $remotehash..$localhash"
        fi

        # shell loops run in subshell if we use a pipe, so use a temp file
        $scancmd >$TF
        while read hash; do
                if check $hash; then status=1; fi
        done <$TF
done
exit $status

Again, this is untested, so test it (and make any required changes to check as there are definitely some required). The general idea here is to scan each commit before git push sends it. When we're augmenting some existing branch in the remote, git rev-list $remotehash..$localhash enumerates the commits we're adding.

There is a flaw here (kind of deliberate): if $remotehash denotes some commit we don't have locally, the git rev-list above will fail. That won't make the overall script fail, but it means they have commits you don't, and you might want to abort the git push. You could fancy this up some more by using git rev-parse --quiet --verify with the $remotehash value: if we can parse it, we have the commit (or tag); if not, we don't. If we don't have it, we may be resetting the branch backwards, or both resetting it backwards and moving it forwards, as --force would. You'll need to decide what, if anything, you'd like to do about this situation.

torek
  • 448,244
  • 59
  • 642
  • 775
  • Thanks @torek. Although I didn't need this but I gained a lot of information by your script which I am sure will be helpful in the future – Prajat Padhi Jul 12 '22 at 19:02
2

But shouldn't in such a case there should be an authorization error as the repository was private in the personal git hub account.
How did GitHub allowed access?

No, commit authorship has nothing to do with authentication/access.

It is better to use a conditional includeIf.<condition>.path global setting in order to set user.name/user.email depending on the project folder you are in.

That way, you don't forget to set the right name/email, and your created commits are done with the right author.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250