Skip to content

Instantly share code, notes, and snippets.

@JoSSte
Last active November 13, 2023 10:24
Show Gist options
  • Save JoSSte/05191d4d222e2a19107dc08d82f63961 to your computer and use it in GitHub Desktop.
Save JoSSte/05191d4d222e2a19107dc08d82f63961 to your computer and use it in GitHub Desktop.
Git tricks

1 Housekeeping

1.1 Remove local cache of deleted branches on remote

When you have merged a branch into another and deleted it on bitbucket, it may still exist on your PC. if you experience that there are too many of these, this command will remove them. Consider cleaning up your local branches first.

git remote update origin --prune

1.2 Clean up local branches

After a sprint you might want to ensure that all your local branches are removed

Executing this command will delete ALL branches except master.

git branch | grep -v "master" | xargs git branch -D
# if your project has another main branch name write that:
git branch | grep -v "main" | xargs git branch -D

2 Code Gymnastics

2.1 Fetch a single file from another branch

Make sure that you are on the branch that you want to copy the file to. The path is relative to where you are in your current branch. Then execute this command:

git checkout feature/otherbranch -- path/to/file

2.2 Merging two git repositories into one

Based on this guide. Let's say that you want to merge RepoA stored in folder RepoA including its history into RepoB stored in folder RepoB
This guide assumes that you are using a variant of bash NOT windows command line or powershell

2.2.1 Prepare RepoA to be merged

  1. Make sure that you are in the correct branch and that you have the newest version of the code. (If you are using github/bitbucket you COULD archive the repository to ensure that noone commits to it.)
    git checkout master - get the main branch
    git pull - get latest commits
    git checkout -b prepare_merge_to_RepoB - create a new branch for the changes - just in case you mess something up
  2. Reorder the files to prevent merge conflicts
    Move files to a structure that fits the new repository (RepoB)
    • mkdir -p repo-a
    • shopt -s extglob - Extended globbing allows pattern matching
    • git mv -k !(repo-a) repo-a - Move everything into repo-a, excluding the directory repo-a itself (hidden files are not moved)
    • shopt -u extglob
  3. Remove git specific files that may already exists in the destination repo (.gitattributes , .gitignore and .editorconfig)
    git rm -f --ignore-unmatch .gitattibutes  
    git rm -f --ignore-unmatch .gitignore  
    git rm -f --ignore-unmatch .editorconfig
  4. Commit changes
    git commit -m "Preparing for merge to RepoB"

2.2.2 Move to the new repository

  1. Switch to RepoB cd ../RepoB
  2. Add RepoA as a remote
    git remote add -f RepoA ../RepoA
  3. Merge the repositories (if you have missed somehting and there are merge conflicts execute git merge --abort and go back to RepoA and fix it)
    git merge -m "Integrating RepoA" RepoA/prepare_monorepo --allow-unrelated-histories
  4. Remove the remote again
    git remote rm RepoA
  5. Push the changes to the remote
    git push

Delete the old repository after verifying that the changes are complete

3 Comparisons

3.1 Compare two commits

Note that the order is important. The newest commit has to be last. if you want the full commit, then omit the --compact-summary  

git diff --color-moved-ws=allow-indentation-change --compact-summary 1faa426847a 320f73c4096
git diff --color-moved-ws=allow-indentation-change --compact-summary <oldest commit ID> <newest commit ID>

git log --oneline --graph --decorate --abbrev-commit feature/OAuth2.0..feature/PureBackend

3.2 Compare specific file in two commits

Note difftool instead of diff . If you have set up the tooling, this will open in visual studio code. If you want to have only one file shown instead of all files, or files with specific patterns:

git difftool 7958676359d e188f35b043 '*.postman_collection.json'

4 Search and Rescue - Finding "lost" code

Find all commits to specific file

git log --graph --all -- package.json

4.1 Search specific file in repo for string across commits

This bash script is for searching a repository for a specific string in a specific file. sometimes Bitbucket does not do what it says on the tin. update the array with the commits you want to search for in the repository you have checked out.

This scripts puts your local repo in a "detached head" state. When you are done, run git checkout <branchname> (or copy your local git copy to a new folder and do this operation in that)

commits=("c730c6f5cd7" "89f22a43071")

for commit in ${commits[@]}; do
  git checkout $commit
  echo $commit
  grep node my.postman_collection.json
  echo -e "\n\n"
done

4.2 Find orphaned commits

Even if you delete a branch that has not been merged into your main branch, the commits are still there:

git fsck --unreachable |grep commit > unreachable.txt

4.2 Git log relative to now

from the NDC conference "Git hidden gems"

#Pretty log:
git log --pretty='%C(red)%h%Creset%C(yellow)%d%Creset %s %C(cyan)(%ar)%Creset'

# make it  an alias:
git config --global alias.lg "log --pretty='%C(red)%h%Creset%C(yellow)%d%Creset %s %C(cyan)(%ar)%Creset'"

#usage: 

git lg

4.3 review last commit

git diff HEAD^ HEAD

5 Tool Configuration

5.1 Use visual studio code as git editor

https://www.roboleary.net/vscode/2020/09/15/vscode-git.html

git config --global core.editor 'code --wait'

5.2 Sample git config

to open config type git config --global -e

[user]
	name = JoSSte
	email = josste@nowhere.dk

[core]
	#autocrlf = true
	excludesfile =
	editor = code --wait
	ignorecase = false
[diff]
	mnemonicprefix = true
	tool = vscode

[difftool "sourcetree"]
	cmd = '' \"$LOCAL\" \"$REMOTE\"

[difftool "vscode"]
	cmd = code --wait --diff $LOCAL $REMOTE

[mergetool "sourcetree"]
	cmd = "'' "
	trustExitCode = true
[http]
	sslcainfo = \path\to\ca-bundle.crt
	sslbackend = openssl
[credential]
	helper = manager

5.3 Adding GPG signatures to your commits

Github has great guides for this:
Generating a new GPG key
Configuring git and github to use your key

I have added the steps here for ease of access:

  1. Execute gpg --full-generate-key to generate a key
    • Select the default
    • Select 4096 bits
    • Select 0 (does not expire)
    • Verify your choices
    • Type Your name
    • Type your email (match the one in your github/bitbucket account)
    • Type a(n optional) comment. I have genereated three keys for the three pcs i use most often and named each after the pc. In that way I can revoke a key if a machine is compromised/stolen.
    • Select (O)kay
    • When prompted, type a passphrase to protect your key (you will need to type this on the first commit of each session)
  2. Execute gpg --list-secret-keys --keyid-format=long
    • There will be a line like sec rsa4096/839D53D75F63410D the part after the / is the ID of your key.
    • Copy your key ID.
  3. Export your key with `
    gpg --armor --export 839D53D75F63410D
  4. Copy your GPG key, beginning with -----BEGIN PGP PUBLIC KEY BLOCK----- and ending with -----END PGP PUBLIC KEY BLOCK-----
  5. Set up git to use your key :
    git config --global user.signingkey 839D53D75F63410D
  6. (Optional) If you want git to automatically sign all commits execute
    git config --global commit.gpgsign true
  7. Finally log into your github/bitbucket account, find the settings, enter the GPG key.

Further Reading

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