| Both sides previous revisionPrevious revisionNext revision | Previous revision |
| git_cheat_sheet [2018/12/27 18:53] – stephen | git_cheat_sheet [2025/12/04 00:38] (current) – [Who needs to clean up] stephen |
|---|
| editor = 'C:/Program Files (x86)/Notepad++/notepad++.exe' -multiInst -notabbar -nosession | editor = 'C:/Program Files (x86)/Notepad++/notepad++.exe' -multiInst -notabbar -nosession |
| pager = cat | pager = cat |
| | longpaths = true |
| |
| [user] | [user] |
| name = Stephen Heise | name = Stephen Heise |
| email = Stephen@tallguyracing.com | email = Stephen@tallguyracing.com |
| | |
| | [init] |
| | defaultBranch = main |
| |
| [mergetool] | [mergetool] |
| cmd = "/c/Program\\ Files\\ \\(x86\\)/WinMerge/WinMergeU.exe" -u -e $LOCAL $REMOTE | cmd = "/c/Program\\ Files\\ \\(x86\\)/WinMerge/WinMergeU.exe" -u -e $LOCAL $REMOTE |
| |
| | [push] |
| | default = current |
| | autoSetupRemote = true |
| | |
| [alias] | [alias] |
| st = status | st = status |
| ci = commit -m | ci = commit -m |
| ca = commit --amend | ca = commit --amend --no-edit |
| | cu = reset HEAD~ |
| | cuh = reset --hard HEAD~ |
| br = branch | br = branch |
| ba = branch -a | ba = branch -a |
| dt = difftool | dt = difftool |
| fa = fetch -a | fa = fetch -a |
| md = merge origin/develop | tf = !git reset && git checkout -- . && git clean -df |
| cd = checkout develop | as = !git add . && git stash |
| pp = !git pull && git push | pr = !git stash pop && git reset |
| | brdr = push --delete origin |
| | fp = push --force |
| | cp = cherry-pick |
| ln = !git --no-pager log -n50 '--pretty=format:"%Cred%h%Creset %ad %Cgreen%<(10,trunc)%an%Creset %<(80,trunc)%s"' '--date=format:"%Y%m%d %H%M%S"' | ln = !git --no-pager log -n50 '--pretty=format:"%Cred%h%Creset %ad %Cgreen%<(10,trunc)%an%Creset %<(80,trunc)%s"' '--date=format:"%Y%m%d %H%M%S"' |
| | ro2m = !echo 'Rebasing onto master' && git fetch origin master:master && git rebase --onto master master && git pull -r origin master |
| | ro2mfp = !git ro2m && echo 'Force pushing' && git fp |
| |
| [winUpdater] | [winUpdater] |
| prune = true | prune = true |
| </code> | </code> |
| | |
| | ==== Project Specific Settings ==== |
| | |
| | If you need project specific settings, like You Just Go, append this: |
| | <code> |
| | [includeIf "gitdir:C:/Dev/YouJustGo/"] |
| | path = .gitconfig-youjustgo |
| | </code> |
| | |
| | Then create a ''C:\Users\God\.gitconfig-youjustgo'' file with this: |
| | <code> |
| | [user] |
| | name = Stephen Heise |
| | email = stephen.heise@youjustgo.com |
| | </code> |
| | |
| | Verify the settings are correct by running the following. Last one wins. |
| | |
| | ''<nowiki>git config --list --show-origin</nowiki>'' |
| |
| ===== Try Git ===== | ===== Try Git ===== |
| |
| | git init | | | | ''<nowiki>git init</nowiki>'' | | |
| | <nowiki>git config --global core.editor "atom --wait"</nowiki> | Make Atom the default editor. | | | ''<nowiki>git config --global core.editor "atom --wait"</nowiki>'' | Make Atom the default editor. | |
| | <nowiki>git config --global user.name "Stephen Heise"</nowiki> | | | | ''<nowiki>git config --global user.name "Stephen Heise"</nowiki>'' | | |
| | <nowiki>git config --global user.email "Stephen@tallguyracing.com"</nowiki> | | | | ''<nowiki>git config --global user.email "Stephen@tallguyracing.com"</nowiki>'' | | |
| | git status | | | | ''<nowiki>git status</nowiki>'' | | |
| | git add filename.txt | | | | ''<nowiki>git add filename.txt</nowiki>'' | | |
| | git commit -m "Commit message" | | | | ''<nowiki>git commit -m "Commit message"</nowiki>'' | | |
| | git log | | | | ''<nowiki>git log</nowiki>'' | | |
| | git remote add origin https://whatever.com | | | | ''<nowiki>git remote add origin https://whatever.com</nowiki>'' | | |
| | git push -u origin master | -u means remember these settings | | | ''<nowiki>git push -u origin master</nowiki>'' | ''<nowiki>-u</nowiki>'' means remember these settings | |
| | git pull origin master | | | | ''<nowiki>git pull origin master</nowiki>'' | | |
| | git diff head | | | | ''<nowiki>git diff head</nowiki>'' | | |
| | <nowiki>git diff --staged</nowiki> | | | | ''<nowiki>git diff --staged</nowiki>'' | | |
| | git reset octofamily/octodog.txt | unstages a file | | | ''<nowiki>git reset octofamily/octodog.txt</nowiki>'' | Unstages a file. | |
| | <nowiki>git checkout -- octocat.txt</nowiki> | go back to last checkout / undo | | | ''<nowiki>git checkout -- octocat.txt</nowiki>'' | Go back to last checkout / undo. | |
| | <nowiki>git reset --hard origin/master</nowiki> | Throw away all local commits. | | | ''<nowiki>git reset --hard origin/master</nowiki>'' | Throw away all local commits. | |
| | git branch -a | Show local and remote branches. | | | ''<nowiki>git branch -a</nowiki>'' | Show local and remote branches. | |
| | git branch clean_up | Create new branch. | | | ''<nowiki>git branch clean_up</nowiki>'' | Create new branch. | |
| | git checkout clean_up | Switch branches. | | | ''<nowiki>git checkout clean_up</nowiki>'' | Switch branches. | |
| | git checkout -b new_branch | Checkout and create branch at the same time. | | | ''<nowiki>git checkout -b new_branch</nowiki>'' | Checkout and create branch at the same time. | |
| | git checkout filename.txt | Undo local (unstaged) modification. | | | ''<nowiki>git checkout filename.txt</nowiki>'' | Undo local (unstaged) modification. | |
| | git rm '*.txt' | Remove local files and include the removal in the staging area. | | | ''<nowiki>git rm '*.txt'</nowiki>'' | Remove local files and include the removal in the staging area. | |
| | git rm -r folder_of_cats | Recursively remove all folders and files from the given directory. | | | ''<nowiki>git rm -r folder_of_cats</nowiki>'' | Recursively remove all folders and files from the given directory. | |
| | git commit -a | Include the deletion of local files to staging area, do the commit. | | | ''<nowiki>git commit -a</nowiki>'' | Include the deletion of local files to staging area, do the commit. | |
| | git merge clean_up | | | | ''<nowiki>git merge clean_up</nowiki>'' | | |
| | <nowiki>git push origin --delete <branch_name></nowiki> | Delete a **remote** branch. | | | ''<nowiki>git push origin --delete <branch_name></nowiki>'' | Delete a **remote** branch. | |
| | git branch -d <branch name> | Delete a branch. | | | ''<nowiki>git branch -d <branch name></nowiki>'' | Delete a branch. | |
| | git branch -D <branch name> | Force delete a branch. Use if branch not merged. | | | ''<nowiki>git branch -D <branch name></nowiki>'' | Force delete a branch. Use if branch not merged. | |
| | git remote prune origin | Clean up remote branch list. | | | ''<nowiki>git remote prune origin</nowiki>'' | Clean up remote branch list. | |
| | <nowiki>git branch -r --merged develop</nowiki> | List remote branches that have been merged with develop. | | | ''<nowiki>git branch -r --merged develop</nowiki>'' | List remote branches that have been merged with develop. | |
| | <nowiki>git branch -r --no-merged develop</nowiki> | List remote branches that have not been merged with develop. | | | ''<nowiki>git branch -r --no-merged develop</nowiki>'' | List remote branches that have not been merged with develop. | |
| | git push | | | | ''<nowiki>git push</nowiki>'' | | |
| | git push origin <hash>:<branch> | Push up to a certain commit. | | | ''<nowiki>git push origin <hash>:<branch></nowiki>'' | Push up to a certain commit. | |
| | git push origin HEAD~10:<branch> | Push up to the last 10 commits. | | | ''<nowiki>git push origin HEAD~10:<branch></nowiki>'' | Push up to the last 10 commits. | |
| | gitk | A commit viewer. | | | ''<nowiki>git push origin HEAD~10:$(git rev-parse --abbrev-ref HEAD)</nowiki>'' | Push up to the last 10 commits. | |
| | git tag -a tagname -m "commit comment" | Annotated tag (preferred over lightweight tags). | | | ''<nowiki>git push --force origin HEAD~10:$(git rev-parse --abbrev-ref HEAD)</nowiki>'' | Force push up to the last 10 commits. | |
| | git tag tagname | Lightweight tag (good for temporary tags). | | | ''<nowiki>gitk</nowiki>'' | A commit viewer. | |
| | <nowiki>git rebase --interactive 44447348...</nowiki> | Fix up unpushed commit messages. '44447348...' = parent commit hash. | | | ''<nowiki>gitk 'stash@{0}'</nowiki>'' | View the contents of the first stash. | |
| | <nowiki>git log --no-merges --oneline develop..</nowiki> | Show all commits on the current branch. | | | ''<nowiki>gitk --all $(git fsck --no-reflog | Select-String "(dangling commit )(.*)" | %{ $_.Line.Split(' ')[2] })</nowiki>'' | Find a dropped stash. | |
| | **Start new branch** || | | ''<nowiki>git tag -a <tagname> -m "commit comment"</nowiki>'' | Annotated tag (preferred over lightweight tags). | |
| | git checkout -b branch-name | Create new branch and checkout. Unstaged changes are retained. | | | ''<nowiki>git tag <tagname></nowiki>''\\ ''<nowiki>git push origin <tagname></nowiki>'' | Lightweight tag (good for temporary tags). | |
| | <nowiki>git push --set-upstream origin branch-name</nowiki> | Push and create branch on remote. | | | ''<nowiki>git rebase --interactive 44447348...</nowiki>'' | Fix up unpushed commit messages. '44447348...' = parent commit hash. | |
| | **Get new remote branch** || | | ''<nowiki>git log --no-merges --oneline develop..</nowiki>'' | Show all commits on the current branch. | |
| | <nowiki>git pull</nowiki> | Make sure git knows about the remote branch. | | | ''<nowiki>git cherry-pick ebe6942^..905e279</nowiki>'' | Cherry-pick an //inclusive// commit range. | |
| | <nowiki>git checkout --track origin/branch_name</nowiki> | Grab the remote branch. | | | ''<nowiki>git --git-dir=../<other repo>/.git format-patch -k -1 --stdout <commit hash> | git am -3 -k</nowiki>'' | 'Cherry pick' a commit from another repo. | |
| | **Merge branch** || | | ''<nowiki>git remote -v</nowiki>'' | View remote / origin URL. | |
| | git checkout master | | | |
| | git merge branch-name | | | ===== Workflows ===== |
| | **Delete branch** || | |
| | <nowiki>git push origin --delete branch-name</nowiki> | Delete the remote branch. | | ==== Copy commits from one branch to another ==== |
| | git branch -d branch-name | Delete the local branch. | | |
| | **Undo last commit** || | | ''<nowiki>git co <source-branch></nowiki>'' | | |
| | <nowiki>git reset HEAD~</nowiki> | Reverts last commit, but does not change files. Only do if commit is not pushed. | | | ''<nowiki>git rebase -i</nowiki>'' | | |
| | <nowiki>git reset --hard HEAD~1</nowiki> | Reverts last commit and reverts changed files. Only do if commit is not pushed. | | | // Copy the commits you want to clipboard. // | | |
| | **Reset tag position** || | | // Delete all text, save, close. // | Aborts the rebase. | |
| | <nowiki>git co develop</nowiki> | Get on the correct branch. | | | ''<nowiki>git co <target-branch></nowiki>'' | | |
| | <nowiki>git ls-remote --tags</nowiki> | List remote tags. | | | ''<nowiki>git rebase -i</nowiki>'' | Add ''<nowiki>HEAD</nowiki>'' if you only want to append commits. | |
| | <nowiki>git push --delete origin tagname</nowiki> | Delete the remote tag. | | | // Paste the commits. Delete ones you don't want. // | | |
| | <nowiki>git tag -d tagname</nowiki> | Delete the local tag. | | | // Save, close. // | | |
| | <nowiki>git tag tagname</nowiki> | Create the local tag. | | |
| | <nowiki>git push origin tagname</nowiki> | Create the remote tag. | | ==== Start new branch ==== |
| | <nowiki>git ls-remote --tags</nowiki> | Check you got it right. | | |
| | **Commit some stuff workflow** || | | ''<nowiki>git checkout -b branch-name</nowiki>'' | Create new branch and checkout. Unstaged changes are retained. | |
| | <nowiki>git add .</nowiki> | Stage everything. | | | ''<nowiki>git push --set-upstream origin branch-name</nowiki>'' | Push and create branch on remote. | |
| | <nowiki>git stash push --keep-index</nowiki> | Stash and keep staged changes. | | |
| | <nowiki>git reset</nowiki> | Unstage everything. | | ==== Get new remote branch ==== |
| | |
| | | ''<nowiki>git pull</nowiki>'' | Make sure git knows about the remote branch. | |
| | | ''<nowiki>git checkout --track origin/branch_name</nowiki>'' | Grab the remote branch. | |
| | |
| | ==== Merge branch ==== |
| | |
| | | ''<nowiki>git checkout master</nowiki>'' | | |
| | | ''<nowiki>git merge <branch-name></nowiki>'' | | |
| | |
| | ==== Delete branch ==== |
| | |
| | | ''<nowiki>git push origin --delete <branch-name></nowiki>'' | Delete the remote branch. | |
| | | ''<nowiki>git branch -d <branch-name></nowiki>'' | Delete the local branch. | |
| | |
| | ==== Rename branch ==== |
| | |
| | | ''<nowiki>git branch -m <newname></nowiki>'' | Rename the current branch. | |
| | | ''<nowiki>git branch -m <oldname> <newname></nowiki>'' | Rename any branch. | |
| | | ''<nowiki>git push origin --delete <oldname></nowiki>''\\ ''<nowiki>git push origin -u <newname></nowiki>'' | Update remote branch. | |
| | |
| | ==== Undo last commit ==== |
| | |
| | | ''<nowiki>git reset HEAD~</nowiki>'' | Reverts last commit, but does not change files. Only do if commit is not pushed. | |
| | | ''<nowiki>git reset --hard HEAD~1</nowiki>'' | Reverts last commit and reverts changed files. Only do if commit is not pushed. | |
| | |
| | ==== Reset tag position ==== |
| | |
| | | ''<nowiki>git co develop</nowiki>'' | Get on the correct branch. | |
| | | ''<nowiki>git ls-remote --tags</nowiki>'' | List remote tags. | |
| | | ''<nowiki>git push --delete origin tagname</nowiki>'' | Delete the remote tag. | |
| | | ''<nowiki>git tag -d tagname</nowiki>'' | Delete the local tag. | |
| | | ''<nowiki>git tag tagname</nowiki>'' | Create the local tag. | |
| | | ''<nowiki>git push origin tagname</nowiki>'' | Create the remote tag. | |
| | | ''<nowiki>git ls-remote --tags</nowiki>'' | Check you got it right. | |
| | |
| | ==== Commit some stuff workflow ==== |
| | |
| | | ''<nowiki>git add .</nowiki>'' | Stage everything. | |
| | | ''<nowiki>git stash push --keep-index</nowiki>'' | Stash and keep staged changes. | |
| | | ''<nowiki>git reset</nowiki>'' | Unstage everything. | |
| | //Hack, stage, commit...// | | | | //Hack, stage, commit...// | | |
| | <nowiki>git stash pop</nowiki> | Get back original. Will create merge conflicts. | | | ''<nowiki>git stash pop</nowiki>'' **or** ''<nowiki>git stash apply</nowiki>'' | Get back original. Use apply for multi-commits. Will create merge conflicts. | |
| | VS, Take theirs | Resolve conflicts. | | | //VS, Take theirs// | Resolve conflicts. | |
| | <nowiki>git reset</nowiki> | Unstage everything. | | | ''<nowiki>git reset</nowiki>'' | Unstage everything. | |
| |
| ==== Visual Studio Online ==== | ==== Remove last two commits from master ==== |
| |
| <code> | | ''<nowiki>git co HEAD~2</nowiki>'' | | |
| git remote add origin https://tallguy789.visualstudio.com/_git/AnotherTestProject | | ''<nowiki>git co -b masterfixed</nowiki>'' | | |
| git push -u origin --all | | ''<nowiki>git push --delete origin master</nowiki>'' | | |
| | | ''<nowiki>git br -D master</nowiki>'' | | |
| | | ''<nowiki>git br -m masterfixed master</nowiki>'' | | |
| | | ''<nowiki>git push origin --set-upstream master</nowiki>'' | | |
| | |
| | ==== Rebase onto master ==== |
| | |
| | | ''<nowiki>git fetch origin master:master</nowiki>'' | Update the master branch. | |
| | | ''<nowiki>git rebase --onto master <source-branch></nowiki>'' | For example, <source-branch> = '2021.3.7946'. | |
| | | ''<nowiki>git pull -r origin master</nowiki>'' | | |
| | | ''<nowiki>git push --force</nowiki>'' | | |
| | |
| | ==== Split up an existing commit ==== |
| | |
| | | ''<nowiki>git rebase -i</nowiki>'' | | |
| | | Mark commit to be split with 'e' | | |
| | | Save & close | | |
| | | When the rebasing has stopped... | | |
| | | ''<nowiki>git reset HEAD~</nowiki>'' | | |
| | | Edit & commit. | | |
| | | ''<nowiki>git rebase --continue</nowiki>'' | | |
| | |
| | ==== Set up a bare repo ==== |
| | |
| | | ''<nowiki>git init --bare BareRepo</nowiki>'' | | |
| | | ''<nowiki>git clone .\BareRepo\ LocalRepo</nowiki>'' | URL will be something like ''<nowiki>file:///C:/Temp/BareRepo</nowiki>'' | |
| | | ''<nowiki>git ci "Initial commit." --allow-empty</nowiki>'' | If you need an initial commit. | |
| | |
| | ==== Create a test repo ==== |
| | |
| | <code powershell> |
| | $scriptpath = Split-Path $MyInvocation.MyCommand.Path |
| | Push-Location $scriptpath |
| | |
| | $remoteRepoName = 'RemoteRepo' |
| | $localRepoName = 'LocalRepo' |
| | |
| | mkdir $remoteRepoName |
| | git init --bare $remoteRepoName |
| | git clone $remoteRepoName $localRepoName |
| | |
| | # Create an initial commit - optional |
| | git --git-dir "$localRepoName/.git" commit --allow-empty -m 'Initial commit.' |
| | git --git-dir "$localRepoName/.git" push |
| | |
| | Pop-Location |
| </code> | </code> |
| |
| ==== Import from SVN ==== | ===== Import from SVN ===== |
| |
| <code> | <code> |
| git svn clone https://ares/svn/SVNRepository/Presentations --no-metadata --tags=Tags --trunk=Trunk --branches=Branches --authors-file=..\users.txt | git svn clone https://ares/svn/SVNRepository/Presentations --no-metadata --tags=Tags --trunk=Trunk --branches=Branches --authors-file=..\users.txt |
| </code> | </code> |
| | |
| | ===== Who needs to clean up ===== |
| | |
| | Lists the author and date of the last commit on each remote branch. |
| | |
| | Bash: |
| | <code bash> |
| | for branch in `git branch -r | grep -v HEAD`;do echo -e `git show --format="%ai %ar by %an" $branch | head -n 1` \\t$branch; done | sort -r |
| | </code> |
| | |
| | Powershell: |
| | <code powershell> |
| | git branch -r | Where-Object { $_ -notmatch 'HEAD' } | ForEach-Object { |
| | $branch = $_.Trim() |
| | $info = git show --format="%ai %ar by %an" $branch | Select-Object -First 1 |
| | [PSCustomObject]@{ |
| | Info = $info |
| | Branch = $branch |
| | } |
| | } | Sort-Object Info -Descending | Format-Table -AutoSize |
| | </code> |
| | ===== How PRs work ===== |
| | |
| | When you create a PR on GitHub, it also creates some other refs for you. Different providers put these in different locations. |
| | |
| | GitHub puts them under ''refs/pulls''. I don’t believe that git has any rules around these refs, providers can define them however they want. |
| | |
| | If you run ''git ls-remote <remote-name>'' on a repo, you’ll see all of these other magic refs coming through. |
| | |
| | On a GitHub repo with some active and completed pull requests, I see these ones (PR #2 has been closed, PR #1 is still open): |
| | |
| | 5003f86523fa07e325d28f50a749685b93dffcf3 refs/pull/1/head |
| | 57c72505a9beed608fe73f474e77b70cd182616f refs/pull/1/merge |
| | 622ba67a9d1279984dc763eb078d0e5d92ae790f refs/pull/2/head |
| | |
| | I believe that ''pull/1/head'' points to the head of the source branch. Source branch is ''dev'', and it’s pointing at the same commit, so that seems correct ''5003f86523fa07e325d28f50a749685b93dffcf3 refs/heads/dev''. |
| | |
| | ''pull/1/merge'' is what I think they’re referring to as the ‘merge branch’. It’s what the target branch will look like once the PR has merged. |
| | |
| | Note that it’s a different commit hash to main ''7adb1c92faa0ef0065e3aedb95fcdc4f523d79e3 refs/heads/main'' because it’s a different commit. |
| | |
| | Now… to show when and how this changes I’ll need to create a new PR because there are conflicts on that example PR that I’m using. |
| | |
| | As a side note: It seems as though these ''refs/pulls/<number>/merge'' refs just stay where they are if there are conflicts. They don’t go away, they just don’t update. Anyway… |
| | |
| | Say we have a default branch ''main'' and some branch with some changes called ''some-changes''. Here is what the refs look like on the remote. |
| | |
| | a94afcad87e765e18d590cc4090a835e210acca6 refs/heads/main |
| | e6317c4e97a465fe2f024e5a3cd5ff3f12c5f6a6 refs/heads/some-changes |
| | |
| | Once I create a PR to merge ''some-changes'' into ''main'' two more refs are added: |
| | |
| | a94afcad87e765e18d590cc4090a835e210acca6 refs/heads/main |
| | e6317c4e97a465fe2f024e5a3cd5ff3f12c5f6a6 refs/heads/some-changes |
| | e6317c4e97a465fe2f024e5a3cd5ff3f12c5f6a6 refs/pull/3/head |
| | 6b33d262276e1e5d520ffb8063dedffd6296664d refs/pull/3/merge |
| | |
| | Note ''pull/3/head'' is the same as ''heads/some-changes''. ''pull/3/merge'' is pointing to some other magic commit that doesn’t really exist anywhere. That’s GitHub merging it in the background and creating a ref of what it will look like. |
| | |
| | If I push changes to ''main'', here is what our refs look like: |
| | |
| | 442fcf2d421c26f75339a82bd364d5fcc3bc0a52 refs/heads/main |
| | e6317c4e97a465fe2f024e5a3cd5ff3f12c5f6a6 refs/heads/some-changes |
| | e6317c4e97a465fe2f024e5a3cd5ff3f12c5f6a6 refs/pull/3/head |
| | 3a58fb072ff48e8bebf2c66491332556f3f935ef refs/pull/3/merge |
| | |
| | ''heads/main'' has changed because I made a commit there. ''pull/3/merge'' has changed because the merge of those two branches now looks different. ''heads/some-changes'' and ''pull/3/head'' are the same because they haven’t moved. |
| | |
| | As for what these branches are used for: This is very useful for making sure that your code will still be valid after the merge is complete (not just in your branch). |
| | If there are any changes to the source or target branches, ''refs/pull/<number>/merge'' will update. Useful for stopping poison merges. |
| |
| |