Tools
    overview
    git
    gRPC
    Docker
    Homebrew
Build Tools

Git

Updated: 2022-08-06

Workflow

# Pull updates from remote
$ git pull origin main --rebase

# Commit local changes
$ git add -A
$ git commit --amend

Branch

A branch is like an easy to read reference to a commit hash.

In Git, a branch is a pointer to one specific commit, while a commit is a snapshot of your repository at a specific point in time.

HEAD: "Where am I right now?"

Most of the time, HEAD points to a branch name. HEAD is synonymous with "the last commit in the current branch."

  • attached: in the normal state, HEAD is attached to a branch.
  • detached: HEAD is pointing directly to a commit instead of a branch.

How to fix "detached HEAD"?

Option 1: discard changes and go back. These 2 are equivalent.

$ git switch <branch-name>
$ git checkout <branch-name>

Option 2: create a new branch at the current HEAD.

$ git checkout -b <new-branch-name>

https vs ssh

You can use either https or ssh to connect to remote repo:

  • https:
    • https://github.com/foo/bar.git
    • it will ask for your username and password when you try to connect remote repo
  • git:
    • [email protected]:foo/bar.git
    • it uses ssh keys to verify you identity.
      • Copy and paste your public key(~/.ssh/id_rsa.pub) to Github account
      • Specify the private key in ~/.ssh/config as
Host heroku.com
HostName heroku.com
IdentityFile /Users/username/.ssh/heroku_key

To check your remote

$ git remote show origin
* remote origin
    Fetch URL: https://github.com/foo/bar.git
    Push  URL: https://github.com/foo/bar.git
    HEAD branch: master

git fetch vs git pull

git pull = git fetch + git merge

  • git fetch: remote repo to local repo.
  • git merge: local repo to working directory.
  • git pull: remote repo to local repo AND working directory.

3 copies of a project on your workstation:

  • the working copy where you are editing and building (not committed yet to your repo).
  • your own repository with your own commit history.
  • local “cached” copy of a remote repository.

It doesn't matter what branch you're on when you add a file, only when you commit it. staging area (index) is shared by all branches; committed code (in local repository) is per branch.

check if local branch is up to date

$ git fetch --dry-run

Diff

git diff ...origin

Config

Config file location:

  • Global: ~/.gitconfig
  • System: /etc/gitconfig
  • Local: /git/configcoding

Set a name

$ git config --global user.name "My Name"
$ git config --local user.name "Foo Bar"

Show the name

$ git config --local user.name
Foo Bar

Checkout a Remote Branch

$ git fetch
$ git checkout test

or

$ git checkout -b <branch> --track <remote>/<branch>

Tags

List all tags:

$ git tag -l
1.0.0

Checkout a tag:

$ git checkout tags/<tag_name>
$ git checkout tags/1.0.0

Remove a tag:

# remove local tag
$ git tag -d <tag_name>

# remove remote tag
$ git push origin :[tag]
$ git push origin :refs/tags/<tag_name>

Add All

To add everything to stage, including additions and removals, use

$ git add -A

Undo commits

$ git reset HEAD~1

Now all the changes done in that commit are unstaged and need to be committed again.

Abandon Changes

Abandon changes and revert your tree to the "clean" state of your current branch. Don't use git revert, use:

# Go back to HEAD
$ git reset --hard HEAD

# Go back to the commit before HEAD
$ git reset --hard HEAD^

# Equivalent to "HEAD^"
$ git reset --hard HEAD~1

# Go back two commits before HEAD
$ git reset --hard HEAD~2

Reset to a remote branch

$ git fetch origin
$ git reset --hard origin/master

In increasing order of dangerous-ness:

  • --soft: moves HEAD but doesn't touch the staging area or the working tree.
  • --mixed: moves HEAD and updates the staging area, but not the working tree.
  • --merge: moves HEAD, resets the staging area, and tries to move all the changes in your working tree into the new working tree.
  • --hard: moves HEAD and adjusts your staging area and working tree to the new HEAD, throwing away everything.

Mac OS X Uses Wrong Git Account

If multiple GitHub accounts are logged in using Mac OS X, the account info might be stroed by Keychain Access. Maven release plugin may fails for using wrong Github account.

[ERROR] Provider message:
[ERROR] The git-push command failed.
[ERROR] Command output:
[ERROR] remote: Permission to <...>/<...>.git denied to <...>.
[ERROR] fatal: unable to access 'https://github.com/<...>/<...>.git/': The requested URL returned error: 403

Solution: find Keychain Access in spotlight or by

Applications->Utilities->Keychain Access.app

Search for github and remove the records.

Upstream Remote

Add your own fork as origin remote

$ git remote add origin https://github.com/<your_fork>/<project_name>.git

Add the central repo as upstream remote

$ git remote add upstream https://github.com/<central_repo>/<project_name>.git

To sync up with upstream

$ git fetch upstream
$ git merge upstream/develop

Or

$ git pull upstream develop

Config global user name and email

Global config is in $HOME/.gitconfig; per repo config is in .git/config.

$ git config --global user.name <your_name>
$ git config --global user.email <[email protected]>

Commit in Wrong User/Email

If user is specified in .git/config as

[user]
    name = your_name
    email = [email protected]

however if git is using the wrong user settings after commit

Author: your_name <[email protected]>

Check if you have these settings in env

  • GIT_AUTHOR_NAME
  • GIT_AUTHOR_EMAIL
  • GIT_COMMITER_NAME
  • GIT_COMMITER_EMAIL

Remove those then try again

How do I make Git ignore file mode (chmod) changes?

git config core.fileMode false

or

git config --global core.filemode false

or open .git/config and modify the core section.

Force Push to head

Override the remote HEAD

$ git push origin +HEAD^:master

Show Remote Logs

$ git log origin/main

Branches

# show local branches
git branch

# show remote branches
git branch -r

# show both local and remote branches
git branch -a

git checkout vs git switch

git switch -c <branch name> is equivalent to git checkout -b <branch name>.

To replace two common uses of git checkout: git switch to switch to a new branch after creating it if necessary, and git restore to restore changes from a given commit.