ls-tree
List files in another branch
git -p ls-tree -r --name-only mybranch:mydir
git config
// Set up token authentication for pushing.
// Command taken from actions/checkout.
if (token) {
const credentials = Buffer.from(`x-access-token:${token}`, 'utf8').toString('base64')
core.setSecret(credentials)
await exec.exec(git, ["config", "--local", "http.https://github.com/.extraheader", `AUTHORIZATION: basic ${credentials}`])
}
# Cache credentials for each local directory where you clone a repository
git config --global credential.useHttpPath true
# Use SSH instead of HTTPS when connecting
git config --global url.ssh://git@github.com/.insteadOf https://github.com/
Speed up Git in Windows
# does filesystem operations in parallel to hide latency
git config --global core.preloadindex true
# fixes UAC issues
git config --global core.fscache true
# minimizes the number of files in .git
git config --global gc.auto 256
# get latest commit id
git rev-parse upstream/master
git filter-branch
Remove files in commits
git filter-branch --index-filter 'git rm --cached --ignore-unmatch public/*' HEAD
Remove empty commits
git filter-branch --commit-filter 'git_commit_non_empty_tree "$@"' -f HEAD
Update name and email in commits
git filter-branch --env-filter '
WRONG_EMAIL="nntrn@wrong.com"
NEW_NAME="nntrn"
NEW_EMAIL="17685332+nntrn@users.noreply.github.com"
if [ "$GIT_COMMITTER_EMAIL" = "$WRONG_EMAIL" ]
then
export GIT_COMMITTER_NAME="$NEW_NAME"
export GIT_COMMITTER_EMAIL="$NEW_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$WRONG_EMAIL" ]
then
export GIT_AUTHOR_NAME="$NEW_NAME"
export GIT_AUTHOR_EMAIL="$NEW_EMAIL"
fi
' -f HEAD
Remove commits by author
git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_NAME" != "nntrn" ];
then
skip_commit "$@"
else
git commit-tree "$@"
fi' -f HEAD
git filter
Hide secrets in commits
# ~/.gitconfig or .git/config
[filter "cleanPass"]
clean = sed -e 's/secretpassword/hiddenpassword/g'
smudge = sed -e 's/hiddenpassword/secretpassword/g'
# .gitattributes or .git/info/attributes
.env text eol=lf filter=cleanPass
$ echo "PASSWORD=secretpassword" >.env
$ git add .env
$ git commit -m "Add .env"
$ git show HEAD:.env
PASSWORD=hiddenpassword
$ cat .env
PASSWORD=secretpassword
Source: https://developers.redhat.com/articles/2022/02/02/protect-secrets-git-cleansmudge-filter
Preserve changes
This method creates a new branch from your current one to preserve your changes. The commits on the new branch are undone, and then only the files you want to preserve are recommitted.
# This preserves your old files.
git checkout -b new_branch_name
# See the list of your commits. # Find the hash of the last commit before your changes.
git log
# Where abcdef is the hash found in the step above.
git reset --soft abcdef
# Commit the found files into the new_branch_name.
git commit <files_to_preserve> -m "preserved files"
Global changes
To make global changes across the source tree, it‘s often easiest to use sed with git-ls-files, using -i for in-place changing (this is generally safe, as we don’t use symlinks much, but there are few places that do). Remember that you don't need to use xargs, since sed can take multiple input files. E.g., to strip trailing whitespace from C++ and header files:
sed -i -E 's/\s+$//' $(git ls-files '*.cpp' '*.h')
You may also find git-grep useful for limiting the scope of your changes, using -l for listing files.
sed -i -E '...' $(git grep -lw Foo '*.cpp' '*.h')
Remember that you can restrict sed actions to matching (or non-matching) lines. For example, to skip lines with a line comment, use the following:
'\,//, ! s/foo/bar/g'
| previous command | new command |
|---|---|
git checkout <branch> |
git switch <branch> |
git checkout |
N/A (use git status) |
git checkout -b <new_branch> [<start_point>] |
git switch -c <new-branch> [<start-point>] |
git checkout -B <new_branch> [<start_point>] |
git switch -C <new-branch> [<start-point>] |
git checkout --orphan <new_branch> |
git switch --orphan <new-branch> |
git checkout --orphan <new_branch> <start_point> |
N/A (use git switch <start-point> then git switch --orphan <new-branch>) |
git checkout [--detach] <commit> |
git switch --detach <commit> |
git checkout --detach [<branch>] |
git switch --detach [<branch>] |
git checkout [--] <pathspec>… |
git restore [--] <pathspec>… |
git checkout --pathspec-from-file=<file> |
git restore --pathspec-from-file=<file> |
git checkout <tree-ish> [--] <pathspec>… |
git restore -s <tree> [--] <pathspec>… |
git checkout <tree-ish> --pathspec-from-file=<file> |
git restore -s <tree> --pathspec-from-file=<file> |
git checkout -p [<tree-ish>] [--] [<pathspec>…] |
git restore -p [-s <tree>] [--] [<pathspec>…] |
Source: Answer to What's the difference between git switch and git checkout <branch>
label git diff
MOD_PATTERN='^.+(\[-|\{\+).*$' \
ADD_PATTERN='^\{\+.*\+\}$' \
REM_PATTERN='^\[-.*-\]$' \
git diff --word-diff --unified=0 | sed -nr \
-e "s/$MOD_PATTERN/modified/p" \
-e "s/$ADD_PATTERN/added/p" \
-e "s/$REM_PATTERN/removed/p" \
| sort | uniq -c