===== 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://@github.com/user/repository.git Pull: git remote set-url origin https://@github.com/user/repository.git ===== Miscellaneous workflow tips ===== ==== Keep the commit log clean ==== * Rebase your local branches to squash work-in-progress commits before merging * Use "git pull --rebase" to pull in upstream changes without adding a useless merge commit ==== Preserve public history ==== * Merge branches with "git merge --no-ff"; this is important as it ensures you have a merge commit that allows you to refer to the entire merge as a single unit in case it needs to be rolled back, etc. * If desired, use "git commit --amend" immediately after merging a branch to put comments into the merge commit ==== Ad-hoc release testing ==== - Set up other developers' personal repositories as remotes - git fetch --all - 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 Everyone else: git fetch git checkout git reset --hard / ==== 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 git tag -d git push :refs/tags/ Source of truth (Step 2, for each tag which will keep its name/metadata but point to a new commit object) git tag -f Source of truth (Step 3) git push -f --tags Everyone else (Step 1, for each tag which is being changed) git tag -d 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 ==== Pulling a remote branch from upstream ==== === Check out the upstream branch === git checkout -b --track / === 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 / === Push the new branch to our remote === git push : ==== Removing a completed branch ==== === Delete the remote branch === git push --delete === Delete the local branch === git branch -d === 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 git remote prune