Skip to content

Instantly share code, notes, and snippets.

@CMCDragonkai
Last active May 24, 2024 10:24
Show Gist options
  • Save CMCDragonkai/8356936 to your computer and use it in GitHub Desktop.
Save CMCDragonkai/8356936 to your computer and use it in GitHub Desktop.
Git CLI Recipes #git

Git Recipes

Bring in a Remote Branch

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

Discarding Unstaged Changes

Changes that haven't been added. Any change will be deleted.

# discard the untracked unstaged change, leave it original
git checkout <file>
# discard all untracked unstaged changes, leave it original
git checkout .
# discard all tracked unstaged changes, leave it at HEAD
git reset --hard HEAD
# discard untracked unstaged directories and files, leave it at HEAD
git clean -xdf

The above commands needs more testing, it is still confusing what does what.

Unstaging Staged Changes

Staged means you've added the change with git add. The change will not be deleted.

# discard the staged change, leave the change unstaged
git reset <file>
# discard all staged changes, leave all changes unstaged
git reset

Uncommitting the Most Recent Commit

So if wanted to eliminate a commit back to vanilla one step at a time, we would (1) uncommit the commit, (2) unstage the staged changes, then (3) discard the unstaged changes.

git reset --soft HEAD~

Push Force

This forces a push from your local respository overwriting the remote repository.

git push origin master --force

Pull Force

This forces a pull from the remote repository overwriting the local respository.

git fetch origin
git reset --hard origin/master

Creating Tags

This tags a release from your current committed branch. The X can be any semantic versioning string.

git tag X
git push --tags

Deleting Tags

This deletes tags in your local repository and remote respository. The X can be the version you want to delete.

git tag -d X
git push --delete origin X

Updating Old Tags

Assuming you've released version 1.5, but you need to update 1.4 to 1.4.1 for an urgent bugfix. On your master branch, backup your current state to somewhere else, rollback to the commit at 1.4, make your necessary changes for 1.4.1 and commit. Then branch out to a different branch like "1.4". Then you tag this current branch 1.4.1. After this you can switch back to master, re-add your 1.5 commits from your backup and delete your "1.4" branch if you don't need it.

git reset --hard <commit id>
MAKE CHANGES
git commit -m '<commit message>'
git branch 1.4
git tag 1.4.1
git push --tags
git checkout master
REVERT BACK TO 1.5
git branch -d 1.4

Although you should probably keep branches of each major version, so you can easily add new minor changes.

Changing Commit Message

If it's the immediate commit message:

git commit --amend

If it's an older commit message, then;

git rebase --interactive <commitsha>

Choose the <commitsha> of the commit right before the message you want to edit. Leave the commits that you don't want to edit as pick, and the ones you do want to edit as reword.

Showing Branches and What they are Tracking

git branch -v
git branch -vv # like a superpowered git status

Set Branch to Track Remote Branch

git branch <branch1> --set-upstream-to <remote>/<branch2> 

Fix your HEAD to a particular commit

It will discard everything and make your current branch the same as the specified treeish.

git reset --hard HEAD
git reset --hard <hash>
git reset --hard <remote>/<branch> # this one is great in combination with git fetch

Pull in Remote and Rebase Local Changes on Top

This is useful when you're tracking upstream repository branch, but you have your own changes as well. It will put your own changes on top of the remote changes.

git pull --rebase <remote> <branch>

Push from Source to Destination

Without :<dest>, it is by default <src> and that's from your local repository perspective.

git push <remote> <src>:<dest>

See the <refspec> details on man git-push.

Pull from Source to Destination

Without :<dest>, it is by default <src> and that's from the remote perspective.

git pull <remote> <src>:<dest>

See the <refspec> details on man git-pull.

Submodule Add

Adds a new submodule to a repository. You do not need to clone the repository. And make sure you didn't clone the submodule already.

cd "$(git rev-parse --show-toplevel)"
git submodule add <repo> modules/<repo-name>
git submodule update --init --recursive --depth 1 modules/<repo-name>

If the repository already exists somewhere else on your local system. You can instead use:

git submodule add --reference <existing-repo-path> <repo> modules/<repo-name>

This can reduce the adding time significantly!

Submodule Remove

cd "$(git rev-parse --show-toplevel)"
package="modules/package"
git submodule deinit --force "$package"
git rm --force "$package"
rm --verbose --recursive --force --dir ".git/modules/$package"

Submodule Update

cd "$(git rev-parse --show-toplevel)"
git submodule update --init --recursive --remote --merge modules/<repo-name>

Submodule Change Upstream URI

cd "$(git rev-parse --show-toplevel)"
git config --file=".gitmodules" "submodule.modules/<repo-name>.url" "<repo>"
git submodule sync

Submodule Move

cd "$(git rev-parse --show-toplevel)"
git mv "modules/<repo-name>" "newmodules/<repo-name>" 

Submodule Status

cd "$(git rev-parse --show-toplevel)"
git submodule status --recursive

Submodule Recursive Push

Pushes changes to all submodules.

git push --recurse-submodules=on-demand

Submodule Recursive Pull

Pulls in changes from all submodules.

git submodule foreach git pull origin master

Submodule Recursive Clone

Clones a repository and all submodules. The X is the URL to the repository.

git clone --recursive X

Building an Archive for Distribution

This is quite useful when you want to build an archive while respecting .gitignore.

git archive --prefix='project_name/' HEAD -o ./build.tar.gz

Specifying HEAD allows you build an archive from the current HEAD commit.

You would generally use this to build an archive for source distribution, where the end-consumer still needs to install dependencies (because your dependencies are probably ignored in your source code), and compile the end-result.

If you want an archive for compiled distribution, this would depend on your target environment and/or target consumer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment