Skip to content

Instantly share code, notes, and snippets.

@jaygooby
Last active November 14, 2024 17:04
Show Gist options
  • Save jaygooby/2762353 to your computer and use it in GitHub Desktop.
Save jaygooby/2762353 to your computer and use it in GitHub Desktop.
Git, you bloody git

Overwrite untracked files in current branch from a remote branch

In a similar vein to git reset --hard feature/weavils you can just overwrite untracked working files (typically left over from branch experiments) which are part of the remote branch you're pulling like this:

git reset --hard origin/feature/weavils

Normally, if you tried git checkout feature/weavils you'd get warnings like untracked working tree files would be overwritten by merge, so hit them with the --hard hammer instead.

(Found via https://stackoverflow.com/q/17404316/391826 and one of the answers: https://stackoverflow.com/a/36824493/391826)

copy from branch into an existing branch without merging

I know I want everything from the feature/weavils branch, with no merging, into my existing checked out branch

git reset --hard feature/weavils

You'll need to git push --force after doing this. And be ready with the 🙉 for your colleagues' wails and gnashing of teeth!

checkout a file from an earlier commit without staging

I wanted to revert a file from an earlier commit, but without staging it, so I could discard some hunks:

git restore --source <commit>  path/to/file

Thanks to this question: https://stackoverflow.com/questions/50158417/git-checkout-file-from-branch-without-changing-index

Initialising a new repo with a different initial branch

After working on some new code, I realised I wanted to push it to an existing remote git repo, but in a branch that didn't exist. The code hadn't been pulled from anywhere - it was newly written in a directory.

Initialise the directory with the branch that you want it to become, commit the code, add the existing remote and push:

git init --initial-branch=my-fun-feature
git add -A && git commit -m "WIP"
git remote add origin example.org:~/example.git
git push --set-upstream origin my-fun-feature

Tracking remote branches after a --single-branch checkout

If you single-branch cloned a repo, you can't track and checkout other branches as you normally would. First you need to explicitly add them:

git remote set-branches --add origin feature/weevils
git fetch origin
git checkout feature/weevils

If you don't do this, then typically you'd see:

git checkout --track feature/weevils
$ fatal: 'feature/weevils' is not a commit and a branch 'weevils' cannot be created from it

Do a pickaxe style search through all your stashes

git stash list -S "the thing" -p

A treasure trove of git scripts

John Wiegley has a ton of useful git scripts which he's collected from around the net: https://github.com/jwiegley/git-scripts

Fast forwarding a branch without checking it out

https://samuelgruetter.net/blog/2018/08/31/git-ffwd-without-checkout/ has a really nice post about branch fast forwarding and fetching, and some detail on what's going on when you do something like:

git fetch origin master:master

And even more interestingly:

git fetch . feature:master

where you're fetching from your local repo . and pushing from your feature branch to your master branch.

Remove all local tracking branches to a remote & then delete the remote

git remote prune origin && git remote rm origin

Force checkout a branch to avoid the commit or stash your changes warning

Sometimes when you want to checkout a branch, even though your current branch is clean, you'll get a failed partial checkout, because a file in your current branch will be changed by the new branch (Looking at you .xcodeproj files). As long as you know your current branch is clean and up-to-date, -f force the checkout

git checkout -f the_branch

Getting merge conflicts when pulling even after -reset --hard HEAD?

git fetch origin
git reset --hard origin/master

Hard reset to HEAD a single file

git checkout HEAD -- some/folder/or/file/path

Want to go back to yesterday, a week ago, 2 months ago, to a specific date?

git checkout @{yesterday}
git checkout @{1.week.ago}
git checkout @{2.months.ago}
git checkout @{"2019-04-26"}

Via https://twitter.com/jaygooby/status/996308522680897537 - loads more git date usages here: https://alexpeattie.com/blog/working-with-dates-in-git

Want to save your work to a stash but still keep those changes in your working directory?

git stash save --keep-index

Did you screw something up using git?

You should take a look at http://ohshitgit.com/ :)

View a file in a previous commit or stash or other commit-ish place

To view, but not checkout a file, use a commit-ish object like a commit sha, short sha, head or stash identifier

git show 250022c63fab80030dcbc72e8b4bf5aa683d8633:file.txt
git show 250022c63:file.txt
git show stash@{2}:file.txt

Squash all commits in a branch down to a single commit

Great for when you're ready to push your local branch with loads of tiny commits to a public repo, or you want to issue a pull request without all your legacy commits. I didn't want to rebase and squash interactively, because I knew in this case that I wanted a single clean commit to start a new public repository with.

git reset $(git commit-tree HEAD^{tree} -m "A new start")

Found at https://stackoverflow.com/a/23486788/391826 - it's the One Liner solution.

Push all branches to from remote to another remote

This will push all branches on remote-x to remote-y without you needing to have local copies

git push remote-y refs/remotes/remote-x/*:refs/heads/*

You'll need to do the same for tags:

git push remote-y refs/tags/*:refs/tags/*

Thanks to https://stackoverflow.com/a/21133502/391826

Push all branches to new remote

If you've added a new remote, you might want to push all your branches to it:

git push new-remote --all

View log in different branch

Maybe you want to cherry-pick from a different branch and you need to know the commit hash:

git log different-branch

You can also look at the log for a specific file on that branch:

git log different-branch path/to/file

Side-by-side diff

git difftool -y -x "diff --suppress-common-lines -y -W 225" master 0ce112bd6dcbedd128566ce712d8cb5d98d765ae |less

-x to execute the diff command, -y for side-by-side, -W for width of lines

Which branch is a specific commit on?

git branch --contains 90be408084cc37b3bcc67eaf0b406ca4f1f381fd

Thanks http://stackoverflow.com/a/1419637/391826

Show non-merge commits to a branch

git log --first-parent --no-merges HEAD

Escape from detached head state

You just need to checkout the branch you want, e.g.

git checkout master

List branches by most recently changed

git for-each-ref --count=30 --sort=-committerdate refs/heads/ --format='%(refname:short)'

and if you want the most recently changed remote branches, swap refs/heads for refs/remotes. Both these via Stackoverflow.

git for-each-ref --count=30 --sort=-committerdate refs/remotes/ --format='%(refname:short)'

Grep through all stashed code

git stash list -p  | grep -i foo 

Pickaxe search all branches

git log --all -S"foo" -p 

Ignore line-ending differences when diffing

(You can't use this with git difftool or merge though)

git diff --ignore-space-at-eol

Prefer one branch over another when merging

Got a conflict during a merge? Know that you only care about the file in the other branch?

git checkout --theirs file/that/has/conflict

Know that yours is the correct one?

git checkout --ours file/that/has/conflict

Want to merge but know that you want your files to win any conflicts?

git merge -s recursive -X ours

Change a commit message

git commit --amend -m "New commit message"

Add forgotten files to last commit

git add forgotten_file other_forgotten_file ...
git commit --amend

Give a stash a meaningful name

git stash save "Nearly finished the blah feature, but have to fix yak first"

Show stashed files

git stash show stash@{1}

Diff a specific file with one in stash

git diff some_branch:spec/blueprints.rb  stash@{1}:spec/blueprints.rb

Diff just files in stash with a branch

# git difftool stash@{1} 
# would diff the whole current branch against the stash, 
# you probably just want the diffs of the files in the stash

for file in `git stash show --name-only stash@{1}`; do git difftool your_branch:$file stash@{1}:$file; done

Extract a single file from a stash

git checkout stash@{1} -- path/of/file/in/stash.rb
# note, can also pass multiple files to get them all at once
# git checkout stash@{1} -- path/of/file/in/stash.rb path/to/file2.txt path/to/another/file.jpg

Diffing uncommitted versus HEAD

# When you diff you can look at the files committed in HEAD, versus those on disk
#
# on disk:
git diff stash@{0}:spec/blueprints.rb spec/blueprints.rb

# in HEAD:
git diff stash@{0}:spec/blueprints.rb HEAD:spec/blueprints.rb

# staged:
git diff stash@{0} -- spec/blueprints.rb

# this omission of the filename and the separation with -- from the stash works with the other examples too

Diff what's going to be merged

# You're working in feature/my-branch and you want to merge from master
#
# git fetch origin master
# git difftool feature/my-branch...origin/master
#
# Note the three ... 
# Without them you're comparing? which is a different thing entirely
# if it's all looking good, then git merge origin master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment