【Git】Git Snippets📚

250 阅读11分钟

Short code snippets for all your development needs.

The Git snippet collection contains a variety of short tips and tricks for all currently maintained versions of git. It includes most commonly-used commands and covers various use-cases in the form of simplified documentation, complete with multiple examples.

Now, let's start our learning about Git !

Git Configuration🐙

Git aliases⭐

Use the command below to create aliases, replacing <alias> with the name of the alias and <command> with the command to be aliased:

$ git config --global alias.<alias> <command>

Additionally, you can use git config --global -e to open the git configuration file in the git text editor and add many aliases all at once.

$ git config --global -e

Example 1

$ git config --global alias.br branch

Example 2

$ git config --global alias.undo "reset HEAD~1"

Example 3

$ git config --global alias.cm "commit -m 'update on `date +%Y-%m-%d`'"

Useful aliases

[alias]
  co = checkout
  cob = checkout -b
  coo = !git fetch && git checkout
  br = branch
  brd = branch -d
  st = status
  aa = add -A .
  unstage = reset --soft HEAD^
  cm = commit -m
  amend = commit --amend -m
  fix = commit --fixup
  undo = reset HEAD~1
  rv = revert
  cp = cherry-pick
  pu = !git push origin `git branch --show-current`
  fush = push -f
  mg = merge --no-ff
  rb = rebase
  rbc = rebase --continue
  rba = rebase --abort
  rbs = rebase --skip
  rom = !git fetch && git rebase -i origin/master --autosquash
  save = stash push
  pop = stash pop
  apply = stash apply
  rl = reflog

Disable fast forward merging by default⭐

Disables the default fast forwarding on merge commits.

Use git config --add merge.ff false to disable fast-forward merging for all branches, even if it is possible.

You can use the --global flag to configure this option globally.

$ git config [--global] --add merge.ff false

Example

$ git config --global --add merge.ff false

$ git checkout my-branch
$ git merge master
# Will never fast forward even if it's possible

Former merge (Fast-forward)

$ git-log
* a8c017f (HEAD -> master) update on 2021-10-09
* 3a6eba4 (origin/master) 2021年10月 9日  8:47:28
* 4975bc2 update
* ceecd3d hello git cm
*   fc60abe Merge remote-tracking branch 'origin'
|\
| * 38c5cfb users
* | dd7a2ca account
|/
* f6f067d add .gitignore.
* e990479 add remote.txt at gitee
* 620fea2 (origin/main, dev2) update on dev2
* fa343b7 comment

$ git checkout dev1
Switched to branch 'dev1'

$ git merge master
Updating 7163b62..a8c017f
Fast-forward
 .gitignore | 0
 dev2.txt   | 0
 readme.txt | 8 +++++---
 remote.txt | 1 +
 4 files changed, 6 insertions(+), 3 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 dev2.txt
 create mode 100644 remote.txt
 
$ git-log
* a8c017f (HEAD -> dev1, master) update on 2021-10-09
* 3a6eba4 (origin/master) 2021年10月 9日  8:47:28
* 4975bc2 update
* ceecd3d hello git cm
*   fc60abe Merge remote-tracking branch 'origin'
|\
| * 38c5cfb users
* | dd7a2ca account
|/
* f6f067d add .gitignore.
* e990479 add remote.txt at gitee
* 620fea2 (origin/main, dev2) update on dev2
* fa343b7 comment

Configured merge (Merge made by the 'recursive' strategy)

$ git-log
* a8c017f (HEAD -> dev1, master) update on 2021-10-09
* 3a6eba4 (origin/master) 2021年10月 9日  8:47:28
* 4975bc2 update
* ceecd3d hello git cm
*   fc60abe Merge remote-tracking branch 'origin'
|\
| * 38c5cfb users
* | dd7a2ca account
|/
* f6f067d add .gitignore.
* e990479 add remote.txt at gitee
* 620fea2 (origin/main, dev2) update on dev2
* fa343b7 comment

$ git checkout dev2
Switched to branch 'dev2'
Your branch is up to date with 'origin/main'.

$ git merge master
Merge made by the 'recursive' strategy.
 .gitignore | 0
 remote.txt | 1 +
 2 files changed, 1 insertion(+)
 create mode 100644 .gitignore
 create mode 100644 remote.txt

$ git-log
*   270d59c (HEAD -> dev2) Merge branch 'master' into dev2
|\
| * a8c017f (master, dev1) update on 2021-10-09
| * 3a6eba4 (origin/master) 2021年10月 9日  8:47:28
| * 4975bc2 update
| * ceecd3d hello git cm
| *   fc60abe Merge remote-tracking branch 'origin'
| |\
| | * 38c5cfb users
| * | dd7a2ca account
| |/
| * f6f067d add .gitignore.
| * e990479 add remote.txt at gitee
|/
* 620fea2 (origin/main) update on dev2
* fa343b7 comment

Now, do you clear the difference of 'Fast-forward' and 'recursive' strategy ?

List all git aliases

Prints a list of all git aliases.

  • Use git config -l to list all variables set in the configuration file.
  • Use the pipe operator (|) to pipe the output and grep alias to only keep aliases.
  • Use the pipe operator (|) to pipe the output and sed 's/^alias\.//g' to remove the alias. part from each alias.

Example

$ git config -l | grep alias | sed 's/^alias\.//g' 

Set default push branch name⭐

Use the name of the current branch when pushing by default as the name of the remote branch.

  • Use git config push.default current to set the name of the remote branch to the one of the current local branch as the default.
  • You can use the --global flag to configure this option globally.
$ git config [--global] push.default current

Example

$ git config --global push.default current

$ git checkout -b my-branch
$ git push -u

Then pushes to origin/my-branch!

Original state:

State changed:

Configure git user information

Configures user information for git.

  • Use git config user.email <email> to set the user's email for the current repository.
  • Use git config user.name <name> to set the user's name for the current repository.
  • You can use the --global flag to configure global user information.
$ git config [--global] user.email <email>
$ git config [--global] user.name  <name>

Example

# Configures user for current repository
$ git config user.email "cool.duck@qua.ck"
$ git config user.name "Duck Quackers"

# Configures global git user
$ git config --global user.email "cool.duck@qua.ck"
$ git config --global user.name "Duck Quackers"

Configure line endings

Configures the line endings for a repository.

  • Use git config core.eol [lf | crlf] to configure the line endings.
  • lf is the UNIX line endings (\n), whereas crlf is the DOS line ending (\r\n).
$ git config core.eol [lf | crlf]

Example

# Configured to use UNIX line endings
$ git config core.eol lf

For more information about this knowledge: About CRLF & LF

Autocorrect git commands

Configure git to autocorrect mistyped commands.

  • Use git config --global help.autocorrect 1 to enable git's autocorrect.
$ git config --global help.autocorrect 1

Example

$ git config --global help.autocorrect 1
# Runs `git status` instead
$ git sttaus

Configure the git text editor

Configure the text editor used by git.

  • Use git config --global core.editor <editor-command> to call <editor-command> as the git text editor.
$ git config --global core.editor <editor-command>

Example

# Sets 'VS Code' as the git text editor
$ git config --global core.editor "code --wait"
# Sets 'vim' as the git text editor
$ git config --global core.editor "vim"

Edit git configuration file⭐

Open the git configuration file in the git text editor.

$ git config --global -e

Git Commit🏆

Propaedeutics🔥

propaedeutics

View commits in a specific date range⭐

Prints all commits in the specified date range.

  • Use git log --since=<date-from> --until=<date-to> to view a log of all commits between <date-from> and <date-on>.
  • You can use only --since=<date-from> to see all commits since a specific date or only --until=<date-on> to view all commits up to a specific date.
  • Use arrow keys to navigate, press Q to exit.
$ git log [--since=<date-from>] [--until=<date-on>]

Example 1

$ git log --since='Apr 1 2021' --until='Apr 4 2021'

Example 2

$ git log --since='2 weeks ago'

View a short summary of commits without merge commits

Prints a short summary of all commits excluding merge commits.

  • Use git log --oneline --no-merges to list a short summary of all commits without merge commits.
$ git log --oneline --no-merges

Example

$ git-log
*   06b7d6b (dev1) Merge branch 'dev2' into dev1
|\
| | * d93117e (HEAD -> master) Commit from the past!!!
| | * e460e34 (gitee/master) Commit from the past
| | * 26fb3b1 update on 2021.10.11
| | * 8f6a3f2 add LICENSE.
| |/
| *   270d59c (gitee/dev2, dev2) Merge branch 'master' into dev2
| |\
| |/
|/|
* | a8c017f update on 2021-10-09
...


$ git log --oneline --no-merges
d93117e (HEAD -> master) Commit from the past!!!
e460e34 (gitee/master) Commit from the past
26fb3b1 update on 2021.10.11
8f6a3f2 add LICENSE.
a8c017f update on 2021-10-09
...

Create a commit with a different date

Sometimes, you might run into a situation where you need to create a commit with a different date than the current one. Luckily, you can handle this using GIT_AUTHOR_DATE and GIT_COMMITTER_DATE :

$ GIT_AUTHOR_DATE='Mon May 18 19:32:10 2020 -0400' \
	GIT_COMMITTER_DATE='Mon May 18 19:32:10 2020 -0400' \
	git commit -m 'Commit from the past'

⭐As shown in the example above, you can set both values to any date you like and your code will be committed on that date. Note that the format for the values above is 'date +"%s %z"' , also referred to as internal raw git format, but you can also use other formats, such as RFC 2822 (Mon, 18 May 2020 19:32:10 -0400), ISO 8601 (2020-05-18 19:32:10 -0400), local (Mon May 18 19:32:10 2020), short (2020-05-18) or relative (5.seconds.ago, 2.years.3.months.ago, 6am yesterday).

Example

Check the date:

View a short summary of commits

Prints a short summary of all commits.

  • Use git log --oneline to list a short summary of all commits.
$ git log --oneline

Manually find the commit that introduced a bug⭐

Uses a binary search algorithm to manually find which commit in history introduced a bug.

  • Use git bisect start to start the process.
  • Use git bisect good <commit> to mark a <commit> as "good", indicating it is known to be bug-free.
  • Use git bisect bad <commit> to mark a different <commit> as "bad" indicating it has the bug.
  • Use git bisect (bad | good) marking each subsequent commit as "good" or "bad" depending if it has the bug or not.
  • Use git bisect reset to reset to the original branch. You can optionally specify a <commit> to reset to.
$ git bisect start
$ git bisect good <commit>
$ git bisect bad <commit>
$ git bisect (bad | good)
$ git bisect reset [<commit>]

Rough Example

$ git bisect start
$ git bisect good 3050fc0de
$ git bisect bad c191f90c7
$ git bisect good # Current commit is good
$ git bisect bad # Current commit is buggy
# ... some time later the bad commit will be printed
$ git bisect reset # Goes to the original branch

Detailed Example🔥

Do you still not understand yet? Don't worry, here shows another detailed example to ensure you catch on it.

git bisect is a useful command to find which commit introduced an error.

The principle is simple: narrow down the history of code submissions in a dichotomy. The idea of "dichotomy" is to split the commit history into two parts, determine whether the problem is in the first or the second half, and continue this process until it narrows down to a single commit record.

This detailed example explains how to use this command with an example. Here is a codebase, clone it to local.

$ git clone git@github.com:bradleyboy/bisectercise.git
$ cd bisectercise

This repository is a web page - index.html. Open it in your browser.

On the page is a counter with two buttons. When you click the '+' button, you can see that instead of incrementing the counter, it decays, indicating that something is wrong with the code.

Now it's time to find out which code commit actually introduced the error. Firstly, check the code commit history.

$ git log --pretty=oneline

As we can see, this repository has a total of 101 commits. The earliest first submitted hash is 4d83cF.

git bisect start starts error checking in the following format:

git bisect start [end-id] [start-id]

In the code above, the "end point" is the most recent commit, and the "start point" is the more recent commit. This history between them is the extent of the error.

In this example, we select the entire code history. The starting point is the first commit 4D83CF and the end point is the most recent HEAD. Of course, you can specify other scopes as well.

$ git bisect start HEAD 4d83cf

After executing the command above, the codebase switches to the commit within the range, which in this case is commit 51(half).

Now refresh the browser and click the '+' button to see that it increments normally. Use git bisect good to indicate that this commit (51st) is ok.

$ git bisect good

Since there is no problem with the 51st commit, it means that the error was introduced later in the code's history. Execute the above command and Git automatically switches to the midpoint of the second half (commit 76).

Now refresh the browser and click the '+' button to see that the increment does not work properly. Use git bisect bad to signal that there is a problem with this commit (76).

$ git bisect bad

After the above command is executed, Git automatically switches to the midpoint of commit 51 to commit 76 (commit 63).

This process is then repeated until the offending commit is successfully found. Git will give you the following prompt.

b47892 is the first bad commit

Now that you've found the problematic commit, you can examine the code to determine exactly what went wrong.

Then, use git bisect reset command to exit the error check and return to the latest code commit.

$ git bisect reset

Now you can start fixing the bug.

(Over)

For more info(ruan-yifeng): ruanyifeng.com/blog/2018/1…

Automatically find the commit that introduced a bug⭐

Uses a binary search algorithm and a given script to find which commit in history introduced a bug.

  • Use git bisect start
  • Use git bisect good <commit> to mark a <commit> as "good", indicating it is known to be bug-free.
  • Use git bisect bad <commit> to mark a different <commit> as "bad" indicating it has the bug.
  • Use git bisect run <command> to run the given <command> on each subsequent commit to find which commit introduce the bug.
  • Use git bisect reset to reset to the original branch. You can optionally specify a <commit> to reset to.
$ git bisect start
$ git bisect good <commit>
$ git bisect bad <commit>
$ git bisect run <commit>
$ git bisect reset [<commit>]

Rough Example

$ git bisect start
$ git bisect good 3050fc0de
$ git bisect bad c191f90c7
$ git bisect run npm test # Run `npm test` for each commit
# ... some time later the bad commit will be printed
$ git bisect reset # Goes to the original branch

Detailed Example🔥

A linear code commit history is a great help in automating problem location, allowing us to go back from the current problematic commit to the first problematic commit in history.

Even better, we can use a split lookup to find the problematic commit in order (LogNLogN) time.

For example, in a codebase, there is a linear commit history between C101C101 and C200C200. We know a test that passes at C101C101 but fails at C200C200. We can checkout C101C101, C102C102, till C200C200, and run the tests after each checkout to find the first commit that fails the test.

However, the method above is extremely inefficient. So, Git provides us with automated test scripts. Here is the demo:

$ git clone git@github.com:jungejason/git-bisect-run-demo.git
cd git-bisect-run-demo

57715@Wu-Yikun MINGW64 /d/Wyk's WorkSpace/git-bisect-run-demo (master)
$ git bisect start

57715@Wu-Yikun MINGW64 /d/Wyk's WorkSpace/git-bisect-run-demo (master|BISECTING)
$ git bisect bad HEAD

57715@Wu-Yikun MINGW64 /d/Wyk's WorkSpace/git-bisect-run-demo (master|BISECTING)
$ git log --grep='C101' --oneline | cat
f1a0469 C101 - change another number

57715@Wu-Yikun MINGW64 /d/Wyk's WorkSpace/git-bisect-run-demo (master|BISECTING)
$ git bisect good f1a0469
Bisecting: 49 revisions left to test after this (roughly 6 steps)
[94d9240b05a108395fb2969fe2a4b6c21fce8e1b] C150 - some change

57715@Wu-Yikun MINGW64 /d/Wyk's WorkSpace/git-bisect-run-demo ((94d9240...)|BISECTING)
$ git bisect run bash test.sh
running bash test.sh
Test Passed
Bisecting: 24 revisions left to test after this (roughly 5 steps)
[8753c8521a465956807e26fe7a3ee79daa5cceb2] C175 - some change
running bash test.sh
Test Passed
Bisecting: 12 revisions left to test after this (roughly 4 steps)
[4e7bafdc9cbab4b2409f7d2d78822200c4578c5b] C187 - some change
running bash test.sh
Test Failed
Bisecting: 5 revisions left to test after this (roughly 3 steps)
[7028c24aea20364fa69af786e31a5e5267c34c36] C181 - some change
running bash test.sh
Test Failed
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[c8e79ede15330e6247cbfe7b212c483483b2433d] C178 - some change
running bash test.sh
Test Passed
Bisecting: 0 revisions left to test after this (roughly 1 step)
[327fc00b43b5041cb2fc626ab8589c607111f164] C180 - some change
running bash test.sh
Test Passed
7028c24aea20364fa69af786e31a5e5267c34c36 is the first bad commit
commit 7028c24aea20364fa69af786e31a5e5267c34c36
Author: Jason Ge <gejun_1978@yahoo.com>
Date:   Tue Oct 1 16:50:32 2019 +0800

    C181 - some change

    Summary: add one line

    Test: none

 inventory.csv | 1 +
 1 file changed, 1 insertion(+)
bisect run success

$ git bisect reset

git bisect run automatically finds C181C181.

7028c24aea20364fa69af786e31a5e5267c34c36 is the first bad commit
commit 7028c24aea20364fa69af786e31a5e5267c34c36
Author: Jason Ge <gejun_1978@yahoo.com>
Date:   Tue Oct 1 16:50:32 2019 +0800

    C181 - some change

    Summary: add one line

    Test: none

 inventory.csv | 1 +
 1 file changed, 1 insertion(+)
bisect run success

For more info: jungejason.github.io/git-bisect-…

Change the last commit's message

Updates the last commit's message without changing its contents.

  • Use git commit --amend -m <message> to replace the last commit's message with the new <message>
$ git commit --amend -m <message>
# or
$ git commit --amend

⭐At this time, if there are any changes in the staging area, they will be submitted together.

Example

$ git add .
$ git commit -m "Fix the newtork."
$ git commit --amend -m "Fix the network Bug."

Attention: While

View commits by author

Prints all commits by the specified author.

  • Use git log --author=<author> to retrieve all commits by the specified <author>.
  • Use arrow keys to navigate, press Q to exit.
$ git log --author=<author>

Example

$ git log --author="wyk"
# commit c191f90c7766ee6d5f24e90b552a6d446f0d02e4
# Author: wyk
# Date: Tue Apr 6 11:11:08 2021 +0300
# [...]

Remove a file from the last commit

Removes a file from the last commit without changing its message.

  • Use git rm —-cached <file> to remove the specified <file> from the index.
  • Use git commit —-amend to update the contents of the last commit, without changing its message.
$ git rm --cache <file>
$ git commit --amend

Example

$ git rm --cached "30-seconds.txt"
$ git commit --amend
# Removes `30-seconds.txt` from the last commit

Commit without running git hooks

Creates a new commit skipping the pre-commit and commit-msg hooks.

  • Use git commit --no-verify -m <message> to commit staged changes without running git hooks.
$ git commit --no-verify -m <message>

Example

# Make some changes to files, ones that your precommit hook might not allow
$ git add .
$ git commit --no-verify -m "Unsafe commit"
# Creates a commit with the message "Unsafe commit", without running git hooks

Edit the last commit

Updates the last commit's contents without changing its message

  • Use git commit --amend --no-edit to add any staged changes to the last commit, without changing its message.
$ git commit --amend --no-edit

Example

$ git add .
$ git commit -m "Fix the network bug"
# Edit or add files
$ git add .
$ git commit --amend --no-edit
# The last commit includes the edited/added files

Rewind back n commits🔥

Rewinds the current branch by a given number of commits.

  • Use git reset HEAD~<n> to rewind the current branch <n> commits.
  • This command will uncommit and unstage changes, but leave them in the working directory.
  • You can use the --hard flag to uncommit, unstage and delete changes instead.
$ git reset [--hard] HEAD~<n>

Example

$ git reset HEAD~5
# Rewinds back 5 commits but keeps changes in the working directory

$ git reset --hard HEAD~3
# Rewinds back 3 commits and deletes changes

Origin state :

execute git reset HEAD~4:

🔥 Tips :

  • HEAD equals with HEAD~0

  • HEAD^ equals with HEAD~1

  • HEAD^^ equals with HEAD~2

  • HEAD^^^ equals with HEAD~3

  • ...

git reset HEAD^: Keeps the changes !

--soft

git reset --hard HEAD^: Deletes changes !

--hard

Rewind back to a specific commit

Rewinds the current branch by a given number of commits.

  • Use git reset <commit> to rewind the current branch to the specified <commit>.
  • This command will uncommit and unstage changes, but leave them in the working directory.
  • You can use the --hard flag to uncommit, unstage and delete changes instead.
$ git reset [--hard] <commit>

Example

$ git reset 3050fc0d3
# Rewinds back to `3050fc0d3` but keeps changes in the working directory

$ git reset --hard c0d30f305
# Rewinds back to `c0d30f305` and deletes changes

Undo a commit

Undoes a specified commit without rewriting history.

  • Use git revert <commit> to revert the specified <commit> , creating a new commit with the inverse of the commit's changes.
$ git revert <commit>

Example

$ git revert 3050fc0d3
# Reverts the commit `3050fc0d3`

Undo the last commit⭐

Undoes the last commit without rewriting history.

  • Use git revert HEAD to revert the last commit, creating a new commit with the inverse of the commit's changes.
$ git revert HEAD

Example

$ git revert HEAD
# Reverts the last commit

As you can see, revert is differed from reset, because revert retains historical commits(but undoes the staging area and workspace), reset not.

View last commit

Prints the last commit.

  • Use git log -1 to view the last commit.
  • Use arrow keys to navigate, press Q to exit.
$ git log -1

Example

$ git log -1

Create a fixup commit❓

Creates a fixup commit that can be autosquashed in the next rebase.

  • Use git commit --fixup <commit> to create a fixup commit for the specified <commit>.
  • After running git rebase --autosquash, fixup commits will be automatically squashed into the commits they reference.
git commit --fixup <commit>

Example

$ git add .
$ git commit --fixup 3050fc0de
# Created a fixup commit for `3050fc0de`
$ git rebase HEAD~5 --autosquash
# Now the fixup commit has been squashed

Create a commit by a different author

Creates a new commit by the specified author.

  • Use git commit -m <message> to create a new commit with the specified <message>.
  • Use the --author option to change the <name> and <email> of the commit's author.
$ git commit -m <message> --author='<name> <email>'

Example

# Make some changes to files
$ git add .
$ git commit -m "Fix the network bug" --author="Duck Quackers <cool.duck@qua.ck>"
# Creates a commit by `Duck Quackers`

Add files to the staging area

Adds files to the staging area.

  • Use git add <pathspec> to add files to the staging area.
  • <pathspec> can be a filename or a folder.
$ git add <pathspec>

Example

$ git add "update.txt"
# Add the file `update.txt` to the staging area

$ git add src/*.json
# Add all files with a `.json` extension in the `src` directory

$ git add .
# Adds all changes to the staging area

Remove files from the staging area

Removes files from the staging area.

  • Use git restore --staged <pathspec> to remove files from the staging area.
  • <pathspec> can be a filename or a folder.
$ git restore --staged <pathspec>

Example

$ git restore --staged "update.txt"
# Remove the file `update.txt` from the staging area

$ git restore --staged src/*.json
# Remove all files with a `.json` extension in the `src` directory

$ git restore --staged .
# Remove all changes from the staging area

⭐This command(git restore --staged) is distinguished from git rm --cached:

  • git restore --staged: Changes to be committed ==> Changes not staged for commit
  • git rm --cached: Changes to be committed ==> Untracked files

🔥 For more info about Undo: juejin.cn/post/702204…

View a summary of changes between two commits

Prints a summary of changes between two given commits.

  • Use git shortlog <commit>..<other-commit> to view a summary of changes between the two given commits.
  • Use arrow keys to navigate, press Q to exit.
$ git shortlog <commit>..<other-commit>

Example

$ git shortlog 866adb3..HEAD

Discard uncommitted changes⭐

Discards all uncommitted changes to the current branch.

  • Use git reset --hard HEAD to reset the local directory to match the latest commit and discard all unstaged changes.
$ git reset --hard HEAD
# Discards all unstaged changes!

Pick changes from one or more commits❓

Applies the changes introduced by one or more commits.

  • Use git cherry-pick <commit> to pick changes from a single commit.
  • Use git cherry-pick <commit-1> <commit-2>... to pick changes from all space-separated commits.
  • Use git cherry-pick <first-commit>..<last-commit> to pick changes from a range of commits.
$ git cherry-pick (<commit>... | <first-commit>..<last-commit>)

Example

$ git cherry-pick 3050fc0de # Picks changes from the commit `3050fc0de`

$ git cherry-pick 3050fc0de c191f90c7
# Picks changes from the commits `3050fc0de`, `c191f90c7` and `0b552a6d4`

$ git cherry-pick 3050fc0de..c191f90c7
# Picks changes from the commits in the range `3050fc0de` - `c191f90c7`

📚For more info:

Add a commit message template

Sets up a commit message template for the current repository.

  • Use git config commit.template <file> to specify <file> as the commit message template for the current repository.
$ git config commit.template <file>

Example

# Sets message of template.txt as the commit message template
$ git config commit.template template.txt

template.txt:

config and then commit:

commit.template just provide a template-message to reduce the time it takes to edit your submissions, you need to edit the template-message anyhow.
Once you did not edit the message: Aborting commit !

How does Git's fast-forward mode work?📕

Merging a branch is one of the most common operations when working with Git. Depending on your team and projects you've been a part of, you might have heard of or even used Git's fast-forward mode when merging. Fast-forward mode is the default in Git, however GitHub will essentially override this by default and create a merge commit instead.

Fast-forward merge

As stated above, Git's default is to use fast-forward merge. It will take the commits from the branch being merged and place them at the tip of the branch you're merging into. This creates a linear history, which is also the main advantage of using fast-forward merge. If you want to emulate fast-forward merge on GitHub, you can use the "Rebase and merge" option.

Non fast-forward merge

GitHub, on the other hand, uses non fast-forward merge by default. It will create a merge commit at the tip of the branch you're merging into, optionally referencing the branch being merged in the commit message. This has the advantage of keeping track of branches more explicitly than fast-forward merge. If you want to get the same behavior in a Git terminal, you can use the --no-ff flag.

As a side note, you can configure the default Git merge behavior, using git config. To learn how to do so, you can take a look at the relevant snippet.

Merge a branch and create a merge commit⭐

Merges a branch into the current branch, creating a merge commit.

  • Use git checkout <target-branch> to switch to the branch into which you want to merge.
  • Use git merge --no-ff -m <message> <source-branch> to merge a branch into the current branch, creating a merge commit with the specified <message>.
$ git checkout <target-branch>
$ git merge --no-ff -m <message> <source-branch>

--no-ff means Not Fast-forward !

🔥 You can also configure it globally (not recommended), see article: juejin.cn/post/701722…

Git Repository🏭

View differences in changes⭐

Displays differences between staged or unstaged changes and the last commit.

  • Use git diff to view differences between your unstaged changes and the last commit.
  • You can use the --staged option to view differences between your staged changes and the last commit instead.
$ git diff [--staged]

Example

$ git diff
# Displays the differences between unstaged changes and the last commit

$ git diff --staged
# Displays the differences between staged changes and the last commit
  • Distinction
    • unstaged changes: before execute git add . , like this picture:
    • staged changes: after execute git add . , but before git commit -m !

🔥Here shows the operation:

① before git add

git diff

② after git add & before git commit

git diff --staged

③ show the diff after git commit

View a visual graph of the repository

Prints a visual graph of all commits and branches in the repository.

  • Use git log --pretty=oneline --graph --decorate --all to view a visual graph of the whole repository's history.
  • Use arrow keys to navigate, press Q to exit.
$ git log --pretty=oneline --graph --decorate --all

Find lost files❓

Prints a list of lost files and commits.

  • Use git fsck --lost-found to print a list of all dangling objects.
  • All appropriate files will be extracted into the .git/lost-found directory.

Move commits from master to a new branch

Moves local commits from the master branch to a new branch.

  • Use git branch <branch> to create a new branch at the tip of the current master.
  • Use git reset HEAD~<n> --hard to rewind back <n> commits and discard changes.
  • Use git checkout <branch> to switch to the new branch.
  • Only works if the changes have only been committed locally and not pushed to the remote.
$ git branch <branch>
$ git reset HEAD~<n> --hard
$ git checkout <branch>

Example

$ git checkout master
$ git add .
$ git commit -m "Fix network bug"
$ git branch patch-1
# `patch-1` branch is created containing the commit "Fix network bug"
$ git reset HEAD~1 --hard # Remove the commit from `master`
$ git checkout patch-1

For more detailed information: juejin.cn/post/702204…

Reset master to match remote

Resets the local master branch to match the one on the remote.

  • Use git fetch origin to retrieve the latest updates from the remote.
  • Use git checkout master to switch to the master branch.
  • Use git reset --hard origin/master to reset the local master branch to match the one on the remote.
$ git fetch origin
$ git checkout master
$ git reset --hard origin/master # Local `master` branch is now up to date with remote `master`

View "undo" history⭐

View git's reference logs. This is especially useful for finding references that don't show up in commit history.

  • Use git reflog to display the git reference log.
  • View your "undo" history

Because sometimes git log doesn't cut it, especially for commands that don't show up in your commit history.

reflog is basically your safety net after running "scary" commands like git rebase. You'll be able to see not only the commits you made, but each of the actions that led you there.

$ git reflog

vs git-log:

Clone a repository

Clones an existing repository, creating a local copy of it.

  • Use git clone <url> to clone an existing repository from <url> to a local directory. The directory's name will be based on the name of the cloned repository.
  • Alternatively, use git clone <url> [<directory>] to clone the repository into the specified local <directory>.
$ git clone <url> [<directory>]

Example

$ git clone https://github.com/hello/Hello-World.git
# Clones the repository in a new directory named 'Hello-World'
$ cd Hello-World

$ git clone https://github.com/hello/Hello-World.git my-project
# Clones the repository in a new directory named 'my-project'
$ cd my-project

Change the remote URL⭐

Changes the URL of the remote repository.

  • Use git remote set-url origin <url> to change the URL of the remote repository to <url>.
$ git remote set-url origin <url>

Example

$ git remote set-url gitee git@gitee.com:Wu-Yikun/git.git

Git Branch💢

Find branches containing a commit⭐

Prints all the branches containing a specific commit.

  • Use git branch --contains <commit> to see a list of all branches containing <commit>.
$ git branch --contains <commit>

Example

# master
$ git branch --contains 8f6a3f2
# dev1、dev2、master
$ git branch --contains 270d59c

Find branches not containing a commit

Prints all the branches not containing a specific commit.

  • Use git branch --no-contains <commit> to see a list of all branches not containing <commit>
$ git branch --no-contains <commit>

Example

# dev1、dev2
$ git branch --no-contains d93117e

Delete a remote branch

Deletes a remote branch.

  • Use git push -d <remote> <branch> to delete the specified remote <branch> on the given <remote>.
$ git push -d <remote> <branch>

Example

$ git checkout master
$ git push -d gitee patch-1

Later:

Merge a branch

Merges a branch into the current branch.

  • Use git checkout <target-branch> to switch to the branch into which you want to merge.
  • Use git merge <source-branch> to merge a branch into the current branch.
$ git checkout <target-branch>
$ git merge <source-branch>

Example

$ git checkout master
$ git merge patch-1 # Merges the `patch-1` branch into `master`!

View branches sorted by date

Prints a list of all local branches sorted by date.

  • Use git branch --sort=-committerdate to display a list of all local branches and sort them based on the date of their last commit.
  • Use arrow keys to navigate, press Q to exit.
$ git branch --sort=-committerdate

Example

$ git branch --sort=-committerdate

* master
  dev1
  dev2

View merged branches

Prints a list of all merged local branches.

  • Use git branch -a --merged to display a list of all merged local branches.
  • Use arrow keys to navigate, press Q to exit.
$ git branch -a --merged

All branches:

Merged branches:

merged-branches

Unmerged branches:

Delete merged branches

Deletes all local merged branches.

  • Use git branch --merged <branch> to list all branches merged into <branch>.
  • Use the pipe operator (|) to pipe the output and grep -v "(^\*|<branch>)" to exclude the current and the target <branch>.
  • Use the pipe operator (|) to pipe the output and xargs git branch -d to delete all of the found branches.
$ git branch --merged <branch> | grep -v "(^\*|<branch>)" | xargs git branch -d

Example

$ git checkout master
$ git branch
# master
# patch-1
# patch-2

# Assuming `patch-1` is merged into master
$ git branch --merged master | grep -v "(^\*|master)" | xargs git branch -d

$ git branch
# master
# patch-2

Delete detached branches❗

Deletes all detached branches.

Detached branches: No branches are associated and only point to a COMMIT!

  • Use git fetch --all --prune to garbage collect any detached branches.
  • This is especially useful if the remote repository is set to automatically delete merged branches.
$ git fetch --all --prune

Example

$ git checkout master
$ git branch
  dev1
  dev2
* master
  patch-1

# Assuming `patch-1` is detached
$ git fetch --all --prune

$ git branch
  dev2
* master
  patch-1

Copy a file from another branch

Copies a file from another branch to the current branch.

  • Use git checkout <branch> <file> to copy the specified <file> from the specified <branch>.
$ git checkout <branch> <file>

Example

$ git checkout patch-2
$ git checkout patch-1 "patch-1.txt"
# `patch-2` branch now contains the patch-1.txt file from `patch-1`

Rename a branch

Renames a local branch.

  • Use git branch -m <old-name> <new-name> to rename <old-name> to <new-name>.
$ git branch -m <old-name> <new-name>

Example

$ git checkout master
$ git branch -m patch-1 patch-2

View current status

Prints the current status of the working tree.

  • Use git status to view the current status of the working tree.
  • You can optionally add the -sb flag to view the short form of the same output
$ git status [-sb]

Example

$ git status
On branch master
Your branch is behind 'gitee/master' by 10 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   Today's Content.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        fixup-commit.txt
        patch-1.txt
        update - 副本.txt
        update.txt

no changes added to commit (use "git add" and/or "git commit -a")


$ git status -sb
## master...gitee/master [behind 10]
 M "Today's Content.txt"
?? fixup-commit.txt
?? patch-1.txt
?? "update - 副本.txt"
?? update.txt

git status -sb is more concise than git status !

Return to previous branch

Switches back to the last branch.

  • Use git checkout - to switch back to the previous branch.
$ git checkout -

Example

$ git checkout patch-1
$ git checkout master
$ git checkout - # Switches to `patch-1`

Rebase onto another branch❓

Rebases the current branch onto another branch.

  • Use git checkout <branch> to switch to the <branch> to be rebased.
  • Use git rebase <base-branch> to rebase the current branch onto <base-branch>.
$ git checkout <branch>
$ git rebase <base-branch>

Example

$ git checkout patch-1
$ git rebase master
# `patch-1` is rebased onto `master`

$ git checkout patch-2
$ git fetch origin # Fetch latest remote branches
$ git rebase origin/master
# `patch-2` is rebased onto the latest remote `master`

📚Basic information about git rebasewww.yiibai.com/git/git_reb…

Discard untracked changes

Discards all untracked changes to the current branch.

  • Use git clean -f -d to discard all untracked changes to the current branch.
$ git clean -f -d

Example

$ git clean -f -d

View difference between two branches⭐

Displays the difference between two branches.

  • Use git diff <branch>..<other-branch> to view the difference between <branch> and <other-branch>.
$ git diff <branch>..<other-branch>

Example

$ git diff patch-1..patch-2
# Displays the difference between branches `patch-1` and `patch-2`

Rename remote branch⭐

Renames a branch both locally and on the remote.

  • Use git branch -m <old-name> <new-name> to rename the local <old-name> branch to <new-name>.
  • Use git push origin --delete <old-name> to delete the old remote branch.
  • Use git checkout <new-name> to switch to the renamed branch.
  • Use git push origin -u <new-name> to set <new-name> as the remote branch for the renamed branch.
$ git branch -m <old-name> <new-name>
$ git push origin --delete <old-name>
$ git checkout <new-name>
$ git push origin -u <new-name>

Example

$ git checkout master
$ git branch -m patch-1 patch-2    # Renamed the local branch to `patch-2`
$ git push origin --delete patch-1		# Remove remote branch `patch-1`
$ git checkout patch-2
$ git push origin -u patch-2 	# Renames(Create) the remote branch `patch-2`

(Over)

🧠Wish you can benefit from this article.
🔥 And welcome to leave your thoughts in the comments section that we can discuss and share ideas with each other.