DEV Community

Sandrina Pereira
Sandrina Pereira

Posted on • Updated on

Git journal (Yet, another cheatsheet)

Since my early days with Git (2015?), I carried with me a private journal where I'd take note of the most unique git commands I had to use at some point.

Today I'm making this journal public (with some re-touches), hoping it helps someone else. 🤞

Disclaimer: If you are not familiar, here's a friendly video intro to Git.
However, most of the flows in this journal are not quite "beginner"...

Nevertheless, feel free to ask questions, suggest different approaches, or simply tell me which command helped you! :)


Entries


1. Git configuration

Problem: I need to use different git accounts for different projects. To ensure the correct account is being used, you need to setup it:

# Setting the account globally for all the projects...
git config --global user.name "your-username"
git config --global user.email "name@email.com"

# ... or just to a specific project
# (you need to be in the git project folder)
git config --local user.name "your-username"
git config --local user.email "name@email.com"
Enter fullscreen mode Exit fullscreen mode

2.1. Change commits author/email

Problem: I mistakenly used the wrong e-mail on my last commit. I need to change it to a different author

git commit --amend --reset-author 
Enter fullscreen mode Exit fullscreen mode

2.2. Change commits author/email - chapter 2

Problem: I realized I had multiple commits with the wrong e-mail. This magical command made the trick:

  git filter-branch --commit-filter 'if [ "$GIT_AUTHOR_EMAIL" = "old-author@email.com" ];
    then 
        export GIT_COMMITTER_NAME="New Author Name";
        export GIT_COMMITTER_EMAIL=new-author@email.com;
        export GIT_AUTHOR_NAME="New Author Name";
        export GIT_AUTHOR_EMAIL=new-author@email.com;
    fi; git commit-tree "$@"'
Enter fullscreen mode Exit fullscreen mode

3. Cleanup local branches

Problem: When doing git branch, I had a lot of local old branches. I wanted to delete them all.

# delete all branches expect master
git branch | grep -v "master" | xargs git branch -D
Enter fullscreen mode Exit fullscreen mode

or

# Delete all merged branches except the current one
git branch --merged | grep -v '*' | xargs git branch -D
Enter fullscreen mode Exit fullscreen mode

4. Pretty Commit logs

Problem: The output of git log is ugly and unreadable. I want something more friendly.

# Add this to your global .gitconfig
[alias]
lg = log --graph --pretty='format:%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
Enter fullscreen mode Exit fullscreen mode

Now I only use git lg. The logs are much readable, specially to understand the git history and merged branches.

screenshot comparing git log with git lg

5. Renaming case sensitive files

Problem: On Mac, I needed to rename a file already pushed, eg Hello.js -> hello.js. Doing a traditional manual rename does not work on MacOS. Solution:

git mv -f path/to/Hello.js path/to/hello.js
Enter fullscreen mode Exit fullscreen mode

6. Override a file with another branch

Problem: I've changed a file by mistake (it was the devil package-lock.json) and wanted to revert it and be the same as in the master branch.

git checkout master package-lock.json
Enter fullscreen mode Exit fullscreen mode

The file is now how it was, then you just need to commit it again.

7. Override a branch with another branch

Problem: I needed to make branch B look like branch A.

# push branch-a code into branch-b (forced)
git push origin branch-a:branch-b -f
Enter fullscreen mode Exit fullscreen mode

Note in 2021: I don't remember why I did this. Today I do this in a different way:

# checkout branch-a
git checkout branch-a
# push its code to branch-b (forced)
git push origin branch-b -f
Enter fullscreen mode Exit fullscreen mode

8. Quicker amend

Problem: I do amend my commits, very often. I wanted a faster way to do it.

# your global .gitconfig
[alias]
sneak = commit --amend --no-edit
Enter fullscreen mode Exit fullscreen mode
# amend a commit right away without being prompt to edit the commit message.
git sneak
Enter fullscreen mode Exit fullscreen mode

P.S. I remember stealing this from a Tweet, but can't remember who. :/

9. Checkout a PR from a forked branch

Problem: I needed to checkout someone's else PR that was created from a forked repo. My local repo was a fork too.

  • 1. Add the original repo to your fork .git/.gitconfig file
[remote "upstream"]
    url = https://github.com/author/original-repo-name.git
    fetch = +refs/heads/*:refs/remotes/upstream/*
Enter fullscreen mode Exit fullscreen mode
  • 2. Add this 3 magic alias to your global .gitconfig.
[alias]
# Checkout a PR
pr = "!f() { git fetch -fu ${2:-upstream} refs/pull/$1/head:pr/$1 && git checkout pr/$1; }; f"
pr-clean = "!git checkout master ; git for-each-ref refs/heads/pr/* --format=\"%(refname)\" | while read ref ; do branch=${ref#refs/heads/} ; git branch -D $branch ; done && git branch -D pr"
pr-id = "!f() { git fetch upstream pull/\"$1\"/head:pr && git checkout pr; }; f"
Enter fullscreen mode Exit fullscreen mode
  • 3. Use this git alias to checkout new PR by id.
git pr-id 781 # 781 is the PR id.

# to pull the new commits, run the following:
git pr-clean && git pr-id 781
Enter fullscreen mode Exit fullscreen mode

10. Convert a PR branch with merge commits to a clean rebased git history

Problem: I had a PR branch full of commits and merge commits. I wanted to merge it without squashing the commits, but keeping a clean git history. (without the merge commits).

Flow summary: Create a new branch that contains the diffs. Use that branch to reset my PR branch, rewriting the commit history.

# - 0. Safety guard: Create a backup of your feature branch just in case things go wrong.
git checkout -b your-branch--backup


# - 1. Get the diffs between your `feature-branch` and `master`.
## 1.1 go to master and pull the latest version 
git checkout master && git fetch

## 1.2 get the diffs between master and your branch
git merge --squash origin/your-branch


# The files were modified to look like `your-branch`.
# verify it by yourself in your code editor...

# - 2. Create a new branch with these diffs
git checkout -b your-branch--clean

# - 3. Commit the changes to the new branch.
#      You can do it in a single commit or multiple commits.
## This commits all the changes at once
git add . && git commit -m "The new code"

# - 4. Rewrite `your-branch` to match the `your-branch--clean`,
    # cleaning all the messy git history
## 4.1 go to your original branch...
git checkout your-branch

## 4.2 ... and rewrite it to be exactly like the cleaned branch
git reset --hard origin/your-branch--clean


# - 5. That's it! Everything should work as before,
    # but now with a clean commit history.
    # Give it a final check. If all good, push it!
gift push -f
Enter fullscreen mode Exit fullscreen mode

Go to your PR again. It should look exactly the same:

  • Same nº of files changed
  • Same nº of diffs added/removed. But now the commits history is clean now! ✨

P.S. If something went wrong, use the backup branch created at the beginning to start over.

11. Different git configs based on path location

Problem: I had different git configs for multiple projects - for example, different pull config and different users. I needed a better solution than creating multiple local configs per project.

Reference: Conditional git configs

  • 1. Create a gift config per configuration:
.gitconfig
.gitconfig-configA
.gitconfig-configB
Enter fullscreen mode Exit fullscreen mode
# .gitconfig

[includeIf "gitdir:~/Documents/git/folderA/"]
  path = .gitconfig-configA
[includeIf "gitdir:~/Documents/git/folderB/"]
  path = .gitconfig-configB

[core]
   excludesfile = /Users/your-pc-name/.gitignore

[alias]
lg = log --....
# other alias common to everyone...
Enter fullscreen mode Exit fullscreen mode
# .gitconfig-configA.
# project under folderA use userA and pull ff

[user]
  name = Your Name A
  email = your-name-a@email.com

[pull]
  ff = only
Enter fullscreen mode Exit fullscreen mode
# .gitconfig-configB
# projects under folderB use userB and pull rebase

[user]
  name = Your Name B
  email = your-name-b@email.com

[pull]
  rebase = true
Enter fullscreen mode Exit fullscreen mode

12. Restart SSH Agent

Problem: My MacOS (Catalina 10.15.7) does not load correctly all my SSH keys (from different accounts), preventing me from pulling repos with SSH.

Imagine I have a SSH key git@github.com-eagle configured.

# The eagle SSH is list properly in pub key...
cat ~/.ssh/*.pub

# But does not show up in the SSH list...
ssh-add -L
Enter fullscreen mode Exit fullscreen mode

The solution is to restart SSH agent to make it work again.

eval "$(ssh-agent -s)"

# it will output a number (eg 00123). Use it in the next command

kill -9 00123

# finally, verify the SSH connection again.
ssh git@github.com-eagle

# Output: "Hi eagle! You've successfully authenticated"
Enter fullscreen mode Exit fullscreen mode

Reference: Stackoverflow - how to restart ssh-agent

13. Include another repo into your local repo

Problem: As part of the hiring process (me as the interviewer), I review multiple code exercises submitted through a repo. These repos are a copy of a template repo.

To review each exercise repo, instead of cloning them, over and over again, I add them locally to the base template repo.

# You can give any unique name to the remote repo. eg "bunny"

# add the repo and checkout its main branch
git remote add bunny https://github.com/author/reponame.git
git fetch bunny
git checkout bunny main
Enter fullscreen mode Exit fullscreen mode

The advantages of remote add over clone:

  • Cleaner: Keep my computer cleaner without all the similar folders.
  • Faster: No need to npm i each repo because the dependencies are already there (based on the main branch)
  • Easy to compare: It's easier to compare the exercise to the expect result with some other git commands because it's the same codebase.

That's all for now! (2021 August 14th)
Next time I face a problem, I'll update this journal with a new entry :)

Top comments (1)

Collapse
 
picwellwisher12pk profile image
Amir Hameed

waaow. you are good