Skip to content

Latest commit

 

History

History
445 lines (297 loc) · 9.67 KB

File metadata and controls

445 lines (297 loc) · 9.67 KB

A

Add everything except untracked files

If you need to add everything except untracked files, i.e. only update changes to files that are already tracked

git add -u # --update

C

Configuration of keys for different repos

$ cat .ssh/config
# Check the Host line
# Then the remote origin url should be modified from, e.g.
# git@github.com:epfl-lasa/robetarme_ros2_wp5.2.git
# to
# git@github.com-robetarme-user:epfl-lasa/robetarme_ros2_wp5.2.git
Host github.com-robetarme-user
  HostName github.com
  User git
  IdentityFile ~/.ssh/robetarme_passphraseless_key
  IdentitiesOnly yes

# Default identity
Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_iti581_github
  IdentitiesOnly yes

Copy commit from <branch-b> to <branch-a>

Let the commit in question have hash abc123. Then

git checkout <branch-a>
git cherry-pick abc123

D

diff different files across different branches

git diff main:src/file_a.txt feature:src/folder/file_b.txt

F

Fetch by specifying key location

GIT_SSH_COMMAND='ssh -i /path/to/private_key' git fetch origin

Find files changed between commits filtered by regex

Say you want to get all yaml files which changed between two commits

git diff --name-only <commit-sha-1> <commit-sha-2> -- '**/*.yaml'

If you want to diff them

commit_sha1=<commit-sha-1>
commit_sha2=<commit-sha-2>
files=$(git diff --name-only $commit_sha1 $commit_sha2 -- '**/*.yaml')
for file in $files; do git difftool $commit_sha1 $commit_sha2 -- "$file"; done

Forgot to add file(s) to latest commit and realised before pushing?

Don't worry. You can add the file(s) to the latest commit with

git add <forgotten-files>
git commit --amend

H

Hooks

Pre-commit

Install

pre-commit install

Run without committing

pre-commit run -a

L

LFS

Installation

git lfs install

Add stuff to

git lfs track "file-larger-than-100MB.psd"

or place files names and regexes in $REPOSITORY_PATH/.gitattributes

Migrate existing files to LFS (e.g. large files already committed)

git lfs migrate import --include="*.bin,*.zip" --everything

Remove commit-unreferenced stuff from

  1. Delete files
  2. Commit
  3. bash git lfs prune

List files modified or yet untracked

git status --porcelain | awk '{print $2}'

If you add the following to ~/.gitconfig then issuing git changed-files will constitute an abbreviation

[alias]
    changed-files = "!git status --porcelain | awk '{print $2}'"

M

Merge branch but don't commit changes yet

Useful when you need to merge changes but not incorporate all of them

# Switch to target branch (e.g. master)
git checkout target-branch

# Merge but don't commit yet. The use of --no-ff is essential
git merge --no-commit --no-ff source-branch

# Reset a specific file to its state before merge
git checkout HEAD -- path/to/file.txt

# Now commit the merge
git commit -m "Merge source-branch, excluding changes to file.txt"

Unstage everything

git reset

Then you may keep the files that you need and discard the rest.

P

Push by specifying key location

GIT_SSH_COMMAND='ssh -i /path/to/private_key' git push origin main

Force-push but prevent accidental overwrite

--force-with-lease is safer than --force as it will refuse to push if someone else has pushed to the branch in the meantime, thus preventing you from accidentally overwriting their work

R

Rebase and automatically accept changes from branch

TL;DR

variant A

You are on branch master and you want to rebase origin/master on top of it. You can keep the version of origin/master instead of master with

# On branch master
# git rebase origin/master
git checkout --ours -- .

variant B

You are on branch branch and you want to rebase your work on master. You can keep the version of branch instead of master with

# On branch branch
# git rebase master
git checkout --theirs -- .

Long story

It is possible to resolve rebase conflicts automatically by favouring the changes from branch b (the branch being rebased) over those from master (the base branch, the branch onto which b is rebased). However, Git doesn’t do this by default; you need to explicitly instruct it. During a rebase with conflicts, Git pauses and asks you to resolve them. If you want to automatically accept all changes from branch b (i.e., ours in the context of a rebase) you can use:

git checkout --theirs -- .

Caution

During a rebase the meanings of ours and theirs are reversed compared to a merge:

  • ours refers to the incoming base (i.e., master, the branch you're rebasing onto).
  • theirs refers to the current commit from branch b (the one being replayed).

After running the above command in the conflicted directory (or for specific files), stage the resolved files:

git add .

Then continue the rebase:

git rebase --continue

If you want to do this non-interactively for the entire rebase, you can pass a strategy option before the rebase starts:

git rebase -X theirs master

This tells Git to automatically prefer the changes from branch b (the theirs side during rebase) whenever conflicts occur.

Caution

Automatically discarding changes from master may unintentionally remove important updates.

Remove changes introduced by commit

Create a New Commit That Undoes It (git revert)

git revert <commit-hash>

Remove from history

With interactive rebase

git rebase -i <base-branch-or-commit>

Locate the commit you want to remove in the editor. Then change the word pick to drop. Save and close the editor. If rebasing requires resolving conflicts then resolve them and continue the rebase with

git rebase --continue

Restore file to past state using commit hash

git checkout <commit-hash> -- <filename>

Revert multiple commits in one commit

Commits are sequential

git revert --no-commit OLDEST_COMMIT_HASH^..NEWEST_COMMIT_HASH

git commit -m "Revert multiple commits: description of changes"

Commits are scattered

# Revert specific commits (in reverse chronological order - latest first)
git revert --no-commit COMMIT_HASH_n COMMIT_HASH_n-1 ... COMMIT_HASH_n-k

git commit -m "Revert specific commits"

S

Squash commits before pushing

You've made N incremental local commits but you want to squash them into one commit before pushing it.

git rebase -i HEAD~N

An editor will open with a list like:

pick 123abc Commit message 1
pick 456def Commit message 2
pick 789ghi Commit message 3
...
pick 012jkl Commit message N

Change all but the first entries to squash

pick   123abc Commit message 1
squash 456def Commit message 2
squash 789ghi Commit message 3
...
squash 012jkl Commit message N

Save and close the editor. Git will then prompt you to edit the new commit message. You can combine or edit the messages as needed. Then save and close the editor again. After that the commits will be squashed into one.

Squash commits during merge

You need to merge a branch onto master but you want to squash all commits from b into one commit.

git checkout master
git merge --squash <branch>

This does not create a merge commit. Instead it stages all the changes from <branch> into the index. Commit the squashed changes with

git commit -m "A single commit message summarizing all changes between <branch> and master"

Squash commits during rebase

You have multiple commits on one branch that you need to rebase onto master, and there are potential conflicts with each commit. You want to avoid resolving multiple conflicts per commit and instead resolve the potential conflicts of one commit (if there are any after squashing them). Let the branch be my-branch. If you prefer not to rewrite my-branch's history then

  • Create a new branch from master and switch to it
git checkout master
git checkout -b my-branch-squashed

Apply the net changes from my-branch as one commit:

git merge --squash my-branch
git commit -m "Squashed all changes from my-branch"

You can now replace my-branch with my-branch-squashed

# On my-branch-squashed still
git rebase master

If you prefer to rewrite history then do an interactive rebase on my-branch first:

Checkout my-branch

git checkout my-branch

Squash all commits in my-branch into one (relative to master)

git rebase -i master

This opens an interactive editor listing all commits in my-branch that are not in master. In the editor:

  • Keep the first commit as pick.
  • Change all subsequent commits to squash (or s).
  • Save and close.

Git will then prompt you to edit the commit message for the squashed commit. Finalize it and save. Now my-branch has a single commit on top of master. If you want to update master with this change:

git checkout master
git merge --ff-only `my-branch`

U

Unstage everything after add

git reset

V

View file modifications

Introduced in specific commit

git show <commit-hash> -- <file>

Introduced by all affecting commits

git log -p --follow <file>

# List commits only
# git log --follow <file>

When file is only staged

git difftool --cached <file>

Side by side in command line

git diff --word-diff

View ignored files

git ls-files --others --ignored --exclude-standard