Skip to content

Instantly share code, notes, and snippets.

@samdoran
Last active May 20, 2022 15:03
Show Gist options
  • Save samdoran/11403813 to your computer and use it in GitHub Desktop.
Save samdoran/11403813 to your computer and use it in GitHub Desktop.

How the hell do I [...] with git?

Committing

stage all files for commit including deletes

git add -A

commit staged changes

git commit
git commit -m "Message"

unstage a single file

git reset HEAD -- file.rb

unstage all changes

git reset
git reset HEAD
git reset HEAD --
git reset [refspec]

amend the last commit

git commit --amend

Working with local branches

create a new branch

git branch [branch]

rename a branch

git branch -m [oldbranch] [newbranch]

switch branches

git switch [branch]

switch to the last branch

git switch -

create a new branch and immediately check it out

git switch -c [branch]

create a new branch that tracks a remote branch and immediately check it out

git switch -t [localbranch] [remote]/[branchename]

create a new branch automatically from a remote branch

git fetch [remote]
git switch [remote branch name]

create a new branch that does not track a remote branch and immediately check it out

git switch --no-track [localbranch] [remote]/[branchename]

show all branches, local and remote

git branch -a

show all branches that match a pattern

git branch -la '[glob pattern]'

show all branches, local and remote, and what they're tracking

git branch -vva

merge a branch

git checkout [branch to merge into]
git merge [branch with changes I want merged]

delete a branch

git branch -d [branch]

Working with remotes

clone a new repository

git clone [URL] [foldername]

clone a new repository and also initialize all submodules

git clone --recursive [URL] [foldername]

show all remotes and their URL

git remote -v

get changes from a remote

git fetch [remote]

merge changes from a remote branch into working branch

git merge [remote]/[branch]

fetch and merge changes from the remote tracking branch into the current branch

git pull

fetch and reabse changes from the remote tracking branch into the current branch with uncommitted work

git pull --rebase --autostash

update the local branch after a remote branch was force pushed if there are no local commits

git stash save  # Optional, only if there are changes in the work tree
git fetch [remote]
git reset --hard [remote]/[branch]  # !WARNING!: Any local work will be lost
get stash pop   # Optional, only if changes were stashed earlier

preserve local commits if a remote branch was force pushed

git fetch [remote]
git rebase --onto [remote]/[branch] [refspec of remote/branch before force push] [local branch] 

stop tracking a remote branch

git branch --unset-upstream [branch]

set current branch to track a remote branch

git branch -u [remote]/[branch]

push changes to a remote

git push [remote] [localbranch]:[remotebranch]

push changes to a remote and track the remote

git push -u [remote] [localbranch]:[remotebranch]

delete local branches that have been deleted from the remote

git remote prune [remote]

delete a branch from a remote

git push -d [remote] [remotebranch] 

Working with submodules

add existing repo as a submodule

git submodule add [repo URL]

initialize submodules after cloning a repository

git submodule init

fetch the submodule data and checkout the appropriate commit

git submodule update

initialize and update submodules

git submodule update --init

clone a new repository and also initialize all submodules

git clone --recursive [URL] [foldername]

update a submodule

git submodule update --remote [submodule name]

change the remote URL of a submodule

vi .gitmodules
[change the URL of the appropriate module]
git submodule sync

show changes made in submodules

git diff --submodule

completely remove a submodule from a repository

git rm [path to submodule]

clean out submodule directory (but don't remove it from the project)

git deinit [path to submodule]

Making changes to submodules

When submodules are initialized, they are in a detached HEAD state. If you want to work on a submodule, you first need to checkout a branch.

cd [submodule directory]
git checkout my-cool-new-feature

Now that you have a local branch to track your work, make changes and commits like you normally would. To pull in changes made to the upstream submodule:

git submodule update --remote --rebase      # You can also use --merge instead

If you forget the --rebase or --merge, Git will update the submodule to match the remote and reset your project to a detached HEAD state. Your committed changes are still in your local branch.

If, however, you have changes in the submodule that are not committed, the --merge or --rebase will fail. You will need to commit or stash your changes first.

If there are conflicts between your local commits and the remote, you will get the normal merge conflict message. Fix the conflicts, commit the result, then run the --merge or --rebase command again.

Once you are ready to push your submodule changes to the remote, use git push like you normally would.

After you have pushed the submodule code, you need to update the submodule references in the container repository, then push those changes to the container remote.

git commit -am "Update submodule [module name]"
git push

Useful settings for working with submodules

git config --global diff.submodule log
git config --global status.submoduleSummary true
git config --global fetch.recurseSubmodules on-demand
git config --global push.recurseSubmodules on-demand    # Git >= 2.7.0

Data Recovery

show log of recent activity

git reflog

show lost commits

git fsck --lost-found

show the contents of a commit

git show [refspec]

merge a lost commit into the current branch

git merge [refspec]

create a new branch from a lost commit

git switch -c [branch] [refspec]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment