目录
在 HOW - Git 使用(前) 中我们介绍过 Git 相关的原理和初步使用。今天我们将为大家介绍 Git 常用命令和技巧。
Git 常用命令详解
1.
git add
使用
git add
命令用于将文件的修改添加到暂存区 (staging area)。
git add .
:将当前目录及其子目录中的所有变化添加到暂存区。git add <file>
:将指定的文件添加到暂存区。
2.
git reset
使用
git reset
命令一般用于撤销对暂存区的修改。比如
git reset HEAD <file>
可以将指定文件从暂存区移除,但保留工作目录中的修改。
具体来说,
git reset
命令用于重置当前分支的 HEAD 到指定的状态,同时可以选择性地更新暂存区和工作目录。不同的选项(如
--soft
、
--mixed
、
--hard
)会对这三个部分(HEAD、暂存区、工作目录)产生不同的影响。
git reset HEAD
这个命令通常用来将暂存区的更改撤销到与最近的提交(HEAD)一致,但保留工作目录中的更改。具体来说:
- HEAD:不变
- 暂存区:重置到 HEAD
- 工作目录:不变
例如,假设你对文件进行了修改并将它们添加到暂存区:
echo"Some changes"> file.txt
gitadd file.txt
此时,你发现不想暂存这些更改,可以使用
git reset HEAD
:
git reset HEAD file.txt
这会将
file.txt
从暂存区移除,但保留工作目录中的修改。这意味着你仍然可以看到文件的修改,但它们不在暂存区中,不会被下次提交包含。
另外也可以使用
git restore --staged <file>
。
git reset --hard
这个命令将 HEAD、暂存区和工作目录都重置到指定的状态。具体来说:
- HEAD:重置到指定的提交
- 暂存区:重置到与指定提交一致
- 工作目录:重置到与指定提交一致
这意味着所有未提交的更改和暂存区的更改都会被丢弃。
例如,假设你对文件进行了修改并将它们添加到暂存区:
echo"Some changes"> file.txt
gitadd file.txt
此时,你决定丢弃所有更改并恢复到最后一次提交的状态,可以使用
git reset --hard
:
git reset --hard HEAD
这会将
HEAD
、暂存区和工作目录都重置到最近一次提交的状态,所有未提交的更改和暂存区的更改都会被丢弃,工作目录会恢复到最后一次提交的状态。
3.
git checkout
使用
git checkout
命令用于切换分支或恢复文件。
git checkout <branchname>
:切换到指定分支。git checkout -b <branchname>
:创建并切换到新分支。git checkout --track <remote>/<branchname>
:从远程分支创建并切换到新分支。比如git checkout --track origin/feat/pharaoh-0524
git checkout -- <file>
:丢弃工作目录中对指定文件的修改,恢复到最近一次提交的状态。git checkout -- .
可丢弃所有修改。
4.
git commit
使用
git commit
命令用于提交暂存区的修改。
git commit -m "<message>"
:带有提交信息的提交。git commit -a -m "<message>"
:跳过git add
,将所有已跟踪文件的修改提交。git commit --amend
:修改最近一次提交,包括提交信息和内容。这在你想要更正最近一次提交中的错误或添加遗漏的修改时非常有用,并且可以避免产生过多 commit 记录。
关于
git commit --amend
,以下是几个具体例子说明如何使用。
修改最近一次提交的信息
假设你在提交时写错了提交信息,你可以用
git commit --amend
来修改它。步骤:
- 进行一次提交,提交信息有误:
git commit -m"Intial commit"
- 发现提交信息有误,使用
--amend
修正提交信息:
git commit --amend-m"Initial commit"
这会将最后一次提交的信息修改为 “Initial commit”。
添加遗漏的修改到最近一次提交
假设你忘记了一些文件或修改未包含在最近一次提交中,可以用
git commit --amend
将这些更改添加到最后一次提交。步骤:
- 提交你的修改:
echo"Some content"> file1.txt
gitadd file1.txt
git commit -m"Add file1.txt"
- 发现你遗漏了另一个文件的修改:
echo"More content"> file2.txt
gitadd file2.txt
- 使用
--amend
将遗漏的修改添加到最近一次提交:
git commit --amend
这会打开默认的文本编辑器,你可以修改提交信息,保存并关闭编辑器。
file2.txt
的修改将被添加到最近一次提交中。
修改最近一次提交的内容和信息
假设你提交后发现提交信息有误,并且漏提交了一个文件,可以一次性修改提交内容和信息。步骤:
- 初次提交:
echo"Some content"> file1.txt
gitadd file1.txt
git commit -m"Add file1 with some content"
- 发现你遗漏了一个文件并且提交信息有误:
echo"More content"> file2.txt
gitadd file2.txt
- 使用
--amend
修正提交信息和内容:
git commit --amend-m"Add file1 and file2 with content"
这会将
file2.txt
的修改添加到最近一次提交,并修改提交信息为 “Add file1 and file2 with content”。
5.
git rm
使用
git rm
命令用于从工作目录和暂存区中删除文件。
git rm <file>
:删除指定文件。git rm --cached <file>
:仅从暂存区中删除文件,但保留工作目录中的文件。
6.
git mv
使用
git mv
命令用于移动或重命名文件。
git mv <oldpath> <newpath>
:将文件从旧路径移动到新路径。
7.
git log
使用
git log
命令用于显示提交历史记录。
git log
:显示当前分支的提交历史。git log <branchname>
:显示指定分支的提交历史。- 输出格式化: -
git log --oneline
:每个提交一行显示。-git log --graph
:图形化显示分支和合并历史。-git log --pretty=format:"%h - %an, %ar : %s"
:自定义显示格式。-git log --stat
:用于显示提交历史,并包含每个提交的文件修改统计信息。
8.
git reflog
使用
git reflog
命令用于记录对仓库的所有引用操作。
git reflog
:显示引用日志。
它提供了一种方式来查看 HEAD 和其他分支引用在仓库的历史记录中的所有变动。这对于找回丢失的提交或者理解操作历史非常有用。
git reflog
的使用和示例:
1. 基本用法
git reflog
这个命令会显示 HEAD 引用的所有变动历史。每一行都会列出一个变动的记录,包括引用的新值和旧值,以及执行该变动的命令和时间。例如:
1c35d40 HEAD@{0}: commit (amend): Updated README file
4e2f3d2 HEAD@{1}: commit: Added README file
a2b4c6d HEAD@{2}: checkout: moving from master to feature
2. 查看特定分支的引用日志
你也可以查看特定分支的引用日志,例如
master
分支:
git reflog show master
这会列出
master
分支的所有引用变动。
3. 恢复丢失的提交
假设你在操作过程中丢失了一个提交,可以通过
reflog
找回。假设最近的一个提交被丢失了,你可以执行以下步骤:
- 使用
git reflog
查找提交的 SHA-1 值:
git reflog
输出可能会包含类似以下内容:
a1b2c3d HEAD@{0}: reset: moving to HEAD^
d4e5f6g HEAD@{1}: commit: Added new feature
- 找到丢失的提交(例如
d4e5f6g
),然后使用git reset
或git checkout
恢复:
git checkout d4e5f6g
或者
git reset --hard d4e5f6g
9.
git branch
使用
git branch
命令用于管理分支。
git branch <branchname>
:创建新分支。默认基于最新的提交。git branch <branchname> <start-point>
:从指定起点创建新分支。即可以指定commit位置创建一个新分支。git branch -d <branchname>
:删除分支。git branch -v
:显示每个分支的最新提交。git branch --merged
:显示已合并到当前分支的分支。git branch --track <branchname> <remote>/<branchname>
:创建并跟踪远程分支。git branch -r
:查看远端所有分支。
10.
git push
使用
git push
命令用于将本地分支提交推送到远程仓库。
git push
:推送当前分支到远程仓库。git push -u origin <branchname>
:推送分支到远程仓库并设置跟踪关系。
这两个命令的细节可以阅读 HOW - Git 使用(前)
11.
git merge
使用
git merge
命令用于合并分支。
git merge --ff
:快速前进合并。git merge --no-ff
:非快速前进合并,即创建一个新的合并提交。git merge --squash
:将所有更改压缩为一个提交,但不自动提交。
具体来说,
git merge --ff
当目标分支(main)是源分支(feature)的直接祖先时,会执行快速前进合并,这种合并不会创建新的合并提交,只会将目标分支的指针向前移动。
假设我们有以下提交历史:
main:A-B-C
feature:A-B-C-D-E
要将 feature 分支合并到 main 分支:
# 切换到 main 分支git checkout main
# 执行快速前进合并git merge --ff feature
合并后,提交历史会变成:
main:A-B-C-D-E
main 分支直接前进到 feature 分支的最新提交,没有创建新的合并提交。
而对于
git merge --no-ff
来说,会强制创建一个新的合并提交,这有助于保留分支的合并历史。
还是前面的示例,当执行:
git merge --no-ff feature
合并后,提交历史会变成:
main:A-B-C-M
\ /D-E
其中 M 是新的合并提交,它将 C 和 E 合并在一起。
而对于
git merge --squash
来说,会将源分支(feature)的所有更改压缩为一个提交,但不会自动创建提交。你需要在合并后手动提交。
还是前面的示例,当执行:
git merge --squash feature
此时,所有的更改都已应用到工作目录中,但没有自动提交。你需要手动创建一个新的提交:
git commit -m"Squashed changes from feature branch"
合并后,提交历史会变成:
main:A-B-C-S
S 是新的提交,它包含了 D 和 E 的所有更改,但不会显示 D 和 E 的独立提交历史。
12.
git rebase
使用
git rebase
命令用于变基,一般用于将一个分支的修改移到另一个分支的顶端。比如
git rebase <branch>
会将当前分支变基到指定分支上。
通过变基,可以创建一个更为线性的项目历史,这在合并多个特性分支或保持提交历史清晰时特别有用。
假设我们有以下提交历史:
main: A - B - C
\
feature: D - E
这里,
feature
分支是基于
main
分支的
B
提交创建的,现在
main
分支上有新的提交
C
,而
feature
分支有自己的提交
D
和
E
。
- 基本变基操作
我们希望将
feature
分支的修改移到
main
分支的顶端。
# 切换到 feature 分支git checkout feature
# 变基到 main 分支git rebase main
变基后,提交历史变为:
main: A - B - C
feature: A - B - C - D' - E'
变基过程中,
D
和
E
提交被复制并应用到
C
提交之后,形成新的提交
D'
和
E'
。
- 解决变基冲突
在变基过程中,如果存在冲突,Git 会暂停变基过程,并提示解决冲突。解决冲突后,你需要执行以下命令继续变基:
# 解决冲突后,添加解决的文件gitadd conflicted_file
# 继续变基过程git rebase --continue
如果希望中止变基过程,可以使用:
git rebase --abort
- 交互式变基
git rebase
还可以交互式使用,以便在变基过程中修改、删除或合并提交。
# 切换到 feature 分支git checkout feature
# 交互式变基到 main 分支git rebase -i main
这会打开一个文本编辑器,列出所有即将应用的提交:
pick d1f3e3d D
pick e4f5g6h E
在这里,你可以修改每一行前面的命令,比如将
pick
改为
squash
(用
s
缩写形式也可以)以将提交压缩为一个提交,或将
pick
改为
edit
以在应用提交时暂停编辑。
pick d1f3e3d D
s e4f5g6h E
变基与合并的比较
- 变基:将分支的提交移到另一个分支的顶端,形成线性的提交历史。使用变基后,原来的提交会被复制并形成新的提交。这有助于保持提交历史的整洁,但会重写提交历史。
- 合并:将两个分支合并,保留各自的提交历史。合并过程中会创建一个新的合并提交,反映两个分支的合并情况。
变基的优势和劣势
优势:
- 提交历史更加线性和整洁。
- 方便追踪和理解项目的发展历史。
劣势:
- 变基会重写提交历史,因此不适用于已经共享的分支,这也是使用过程中要尤其注意的。重写历史后,其他开发者在拉取变基后的分支时可能会遇到问题。
13.
git fetch
使用
git fetch
命令用于从远程仓库下载更新,但不自动合并。
git fetch origin <branchname>
:下载指定分支的更新。git fetch origin
:下载所有分支的更新。
14.
git pull
使用
git pull
命令用于从远程仓库下载某个分支的更新并与本地指定分支合并,完整形式:
git pull <远程主机名> <远程分支名>:<本地分支名>
。
- 形式1:不带参数的
git pull
当你在本地分支上执行
git pull
时,Git 会默认从与本地分支关联的远程分支拉取更新,并将其合并到本地分支上。
假设你当前在本地的
main
分支上,并且该分支与远程的
origin/main
分支存在关联关系。执行以下命令:
git pull
这会从远程仓库的
origin/main
分支拉取更新,并将其合并到你当前所在的本地
main
分支上。
- 形式2:带参数的
git pull
当你需要从远程仓库的特定分支拉取更新时,可以使用带参数的形式:
git pull <远程主机名><远程分支名>:<本地分支名>
这个命令会将指定远程分支的更新拉取下来,并合并到指定的本地分支上。
假设你想要从远程仓库的
origin
主机的
develop
分支拉取更新,并合并到你当前所在的本地
feature
分支上。执行以下命令:
git pull origin develop:feature
这会从
origin
主机的
develop
分支拉取更新,并将其合并到你当前所在的本地
feature
分支上。
注意事项:
- 如果省略了
<本地分支名>
,Git 会自动使用当前所在的本地分支名。 - 如果省略了
<远程主机名>
,默认使用与当前本地分支关联的远程主机(通常是origin
)。 - 在执行
git pull
前,最好确保当前分支是干净的,即没有未提交的修改或未解决的冲突,以避免不必要的合并冲突。
使用建议:
- 在拉取更新之前,可以使用
git fetch
命令查看远程仓库的更新情况,并决定是否拉取更新。 - 在执行
git pull
时,建议先切换到目标本地分支,然后再执行命令,以避免混淆和错误。 - 注意在多人协作的项目中,避免频繁地使用
git pull
,以免造成不必要的代码冲突和合并问题。
通过理解不同形式下
git pull
命令的用法,可以更加灵活地管理和同步本地和远程仓库的更新。
15.
git tag
使用
git tag
命令用于创建标签。
git tag
:查看所有 taggit tag -a <tagname> -m "<comments>"
:创建带注释的标签。git show <tagname>
:显示标签信息。git push origin <tagname>
:将标签推送到远程仓库。默认情况下 git push 不会把 tag 传到远端,需要通过此命令主动上传。
这些命令和用法涵盖了 Git 中最常用的操作,可以帮助你有效地管理代码版本和进行团队协作。根据具体需求,你可以灵活运用这些命令来提高工作效率。
16.
git revert
使用
git revert
命令用于撤销一个已经提交的变更,但不会修改提交历史,而是通过创建一个新的提交来实现。
这个新的提交会应用指定提交的相反变化,以将代码恢复到撤销的状态。
git revert
常用于撤销一个或多个不正确的提交,同时保留提交历史的完整性。
- 场景1:撤销最近一次提交
假设你最近提交了一些错误的更改,并希望将其撤销:
# 查看最近的提交历史git log --oneline# 执行撤销操作git revert HEAD
这会创建一个新的提交,将最近一次提交的变更撤销掉。
- 场景2:撤销特定提交
假设你想要撤销一个特定的提交,比如提交
a1b2c3d
:
# 查看提交历史,找到要撤销的提交git log --oneline# 执行撤销操作,将提交 a1b2c3d 的变更撤销掉git revert a1b2c3d
这会创建一个新的提交,将提交
a1b2c3d
的变更撤销掉。
- 场景3:同时撤销多个提交
假设你需要一次性撤销多个连续的提交,比如提交范围
a1b2c3d..e4f5g6h
:
# 查看提交历史,找到要撤销的提交范围git log --oneline# 执行撤销操作,将提交范围 a1b2c3d..e4f5g6h 的变更撤销掉git revert a1b2c3d..e4f5g6h
这会创建一个新的提交,将指定范围内的提交的变更撤销掉。
注意事项:
- 撤销操作会创建一个新的提交,因此需要提交撤销更改后的代码。你可以在撤销提交时提供一条清晰的提交消息,描述你为什么进行撤销操作。
- 撤销操作不会删除原始提交,而是创建一个新的提交来应用相反的变化。因此,提交历史会保留原始提交和撤销提交。
- 撤销操作可能会导致代码冲突,特别是在撤销多个提交或涉及到修改同一文件的提交时。在这种情况下,你需要解决冲突并手动提交解决方案。
通过使用
git revert
命令,你可以安全地撤销提交的变更,同时保留提交历史的完整性。这使得团队可以轻松地纠正错误,而不会影响到其他人的工作。
18.
git cherry-pick
使用
git cherry-pick
命令用于从其他分支中提取特定的提交并应用到当前分支。
这个命令通常用于在当前分支上引入其他分支上的单个提交,而不是整个分支的历史。常见的用例包括:将修复或特性提交从一个分支合并到另一个分支,而不是通过合并整个分支来引入这些更改。
- 场景1:从另一个分支中应用单个提交
假设你希望将另一个分支
feature-branch
中的某个提交
abc123
应用到当前分支:
# 切换到当前分支git checkout main
# 应用特定提交到当前分支git cherry-pick abc123
这会在当前分支创建一个新的提交,包含来自
feature-branch
的提交
abc123
的更改。
- 场景2:从其他分支中引入多个提交
假设你希望将另一个分支
feature-branch
中的多个提交引入到当前分支:
# 切换到当前分支git checkout main
# 应用多个提交到当前分支git cherry-pick abc123 def456
这会在当前分支创建多个新的提交,包含来自
feature-branch
的提交
abc123
和
def456
的更改。
- 场景3:解决冲突并继续 cherry-pick
在执行
git cherry-pick
时,如果发生了冲突,你需要解决冲突并继续 cherry-pick 过程:
# 应用特定提交到当前分支,可能会产生冲突git cherry-pick abc123
# 解决冲突# ...# 继续 cherry-pick 过程git cherry-pick --continue
- 场景4:终止 cherry-pick 过程
如果在 cherry-pick 过程中遇到问题,你可以终止 cherry-pick 过程:
# 取消当前 cherry-pick 进程并重置工作目录git cherry-pick --abort
注意事项:
git cherry-pick
可能会产生冲突,特别是当应用的提交与当前分支的其他更改冲突时。在这种情况下,你需要解决冲突并手动提交解决方案。git cherry-pick
只能应用单个提交的更改,而不是整个分支的历史。因此,它适用于引入单个修复或特性提交,而不是合并整个分支的更改。
通过使用
git cherry-pick
命令,你可以在不合并整个分支的情况下,引入其他分支上的特定提交到当前分支,这使得在 Git 项目中进行代码管理和合作更加灵活。
19.
git stash
使用
git stash
命令用于临时存储未提交的修改,保持工作目录的清洁。
git stash
:将当前工作目录的修改保存到一个新的存储区。
git stash
git stash pop
:应用最近的存储,并将其从存储列表中移除。
git stash pop
git stash list
:列出所有的存储。
git stash list
20.
git diff
使用
git diff
命令用于显示两个提交之间的差异,或工作目录和暂存区之间的差异。
git diff
:显示工作目录中未暂存的变化。
gitdiff
git diff --staged
:显示暂存区和最新提交之间的差异。
gitdiff--staged
git diff <commit1> <commit2>
:显示两个提交之间的差异。
gitdiff a1b2c3d..d4e5f6g
21.
git blame
使用
git blame
是 Git 中的一个命令,用于显示每一行代码的最后修改信息。它是一个非常有用的工具,特别在以下场景中:
- 了解某行代码的历史:谁写的,什么时候写的,以及为什么写。
- 追踪代码中的Bug:找到相关代码的最后修改者,了解变更的原因。
- 代码审查和学习:查看某段代码的历史演变过程,学习编程技巧和最佳实践。
基本用法:
命令格式
git blame [options]<file>
常用选项
-L <start>,<end>
:只显示指定范围的行的blame信息。-C
:检测被拷贝或移动的代码,并显示原始提交信息。-M
:检测被移动或重命名的文件,并显示原始提交信息。
示例1:查看整个文件的blame信息
git blame example.js
这将显示
example.js
文件的每一行的修改信息。
示例2:查看文件的部分内容的blame信息
git blame -L10,20 example.js
这将显示
example.js
文件第10行到第20行的blame信息。
示例3:
git blame -C-M example.js
这将显示
example.js
文件的blame信息,并且会检测被移动或重命名的代码。
输出解释:
运行
git blame
命令后,输出会显示每一行代码的相关信息,例如:
^3e2f1d4e (Alice Smith 2023-04-10 14:23:45 +0800 1)function add(a, b){
^3e2f1d4e (Alice Smith 2023-04-10 14:23:45 +0800 2)return a + b;
^2d5f3e2f (Bob Brown 2023-05-01 10:15:30 +0800 3)}
每一行信息包含以下部分:
- 提交哈希 (
^3e2f1d4e
) - 作者名称 (
Alice Smith
) - 提交日期 (
2023-04-10 14:23:45 +0800
) - 行号(
1
,2
,3
)
版权归原作者 @PHARAOH 所有, 如有侵权,请联系我们删除。