Table of Contents

GitHub tricks

Using an API token for authenticated HTTPS

Create a token: “Account Settings > Applications > Personal Access Tokens > Create new token”

Clone:

git clone https://<token>@github.com/user/repository.git

Pull:

git remote set-url origin https://<token>@github.com/user/repository.git

Miscellaneous workflow tips

Keep the commit log clean

Preserve public history

Ad-hoc release testing

  1. Set up other developers' personal repositories as remotes
  2. git fetch –all
  3. git checkout other-developer/feature

Change commit author information

You can't really do this on commits you've pushed (if you've decided you absolutely must, see the “Rewriting shared history” section). Use this on a local project that you're about to push to a public repository for the first time, to set a consistent/different author identity.

Change a specific author name:

git filter-branch -f --commit-filter '[ "${GIT_AUTHOR_NAME}" = "Old Name" ] && export GIT_AUTHOR_NAME="New Name"; git commit-tree "$@"'

Change a specific author email:

git filter-branch -f --commit-filter '[ "${GIT_AUTHOR_EMAIL}" = "old@example.com" ] && export GIT_AUTHOR_EMAIL="new@example.com"; git commit-tree "$@"'

Change all names/emails:

git filter-branch -f --commit-filter 'GIT_AUTHOR_NAME="New Name" git commit-tree "$@"'
git filter-branch -f --commit-filter 'GIT_AUTHOR_EMAIL="new@example.com" git commit-tree "$@"'

Both at once (specific):

git filter-branch -f --commit-filter '[ "${GIT_AUTHOR_NAME}" = "Old Name" ] && export GIT_AUTHOR_NAME="New Name"; [ "${GIT_AUTHOR_EMAIL}" = "old@example.com" ] && export GIT_AUTHOR_EMAIL="new@example.com"; git commit-tree "$@"'

Both at once (all):

git filter-branch -f --commit-filter 'export GIT_AUTHOR_NAME="New Name"; export GIT_AUTHOR_EMAIL="new@example.com"; git commit-tree "$@"'

Rewriting shared history

Commit log

First off: if you're doing this, you've done something fundamentally wrong. That said, if you do need to, here's how you can do it. First, everyone who shares the repo decides on one person who will coerce the history to the desired state (using rebase, reset –hard, octopus merge, whatever). Once the “source of truth” has the desired history, proceed as follows.

Source of truth:

git push -f <shared-remote> <branch>

Everyone else:

git fetch <shared-remote>
git checkout <local-branch>
git reset --hard <shared-remote>/<shared-branch>

Tags

First off: you especially shouldn't be doing this. But again, if you must do so… Everyone who shares the repository nominates a “source of truth” and proceeds as follows. Caveat: I'm not sure how/if this will work for tags with metadata (annotations, signatures, etc.); this is just for “lightweight” tags.

Source of truth (Step 1, for each tag which is to be renamed but stay on the same commit object):

git tag <new-name> <old-name>
git tag -d <old-name>
git push <shared-remote> :refs/tags/<old-name>

Source of truth (Step 2, for each tag which will keep its name/metadata but point to a new commit object)

git tag -f <tag-name> <commit-object>

Source of truth (Step 3)

git push -f --tags <shared-remote>

Everyone else (Step 1, for each tag which is being changed)

git tag -d <tag-name>

After doing the above, everyone else will get the updated tags the next time they fetch/pull. Everyone should also be sure to remove the tags from any other (non-shared) remotes, or they may find their way back into the shared repository.

Working with remote branches

Creating a new branch and pushing it upstream

git checkout -b newbranch
git push --set-upstream <remote> <newbranch>

Pulling a remote branch from upstream

Check out the upstream branch

git checkout -b <newbranch> --track <remote>/<newbranch>

Update branch remote configuration

If you don't do this, the branch will continue to track the upstream remote (so if that's what you want, skip this step).

git branch --set-upstream <newbranch> <remote>/<newbranch>

Push the new branch to our remote

git push <remote> <newbranch>:<newbranch>

Removing a completed branch

Delete the remote branch

git push <upstream-remote> --delete <mybranch>

Delete the local branch

git branch -d <mybranch>

Remove remote tracking

It only makes sense to do this after the branch has been removed from the remote, or you'll just get it again the next time you fetch.

git remote prune <my-remote>
git remote prune <upstream-remote>