git init
用于创建新的 Git
仓库的命令。当你想要开始跟踪一个新项目或将一个现有项目转换为 Git
仓库时,可以使用这个命令。
它会在当前目录下生成一个 .git
子目录,在其中写入 Git
的配置和项目的快照。这个目录包含了 Git
仓库的所有配置和版本历史信息。不要手动修改或删除 .git
目录,因为它是 Git 仓库的核心。
shell
# 创建新仓库
git init
git init
通常用于创建本地仓库,但在克隆远程仓库时,Git
会自动执行git init
并创建一个本地仓库的副本。
初始化仓库后,你可以配置 Git
,包括设置用户名和电子邮件地址,以及定义 .gitignore
文件来忽略不需要跟踪的文件。
git config
Git
配置相关的指令,像配置 user
、email
等。
shell
# 检查一下用户名和邮箱是否配置
git config --global --list
# 设置全局用户
git config --global user.name 'your name'
git config --global user.email 'xxxxx@example.com'
# 设置局部用户(在指定项目目录下,可配置不同项目有不同的git用户)
git config user.name 'ccc'
git config user.email 'xxxxx@example.com'
# 设置全局的一次性修改配置
git config --global --edit
# 查看全局配置
cat ~/.gitconfig
git 生成密钥
shell
ssh-keygen -t rsa -c 'xxxxx@example.com'
git remote
用于管理与远程仓库相关的操作,包括查看、添加、删除、重命名和更新远程仓库。
shell
# 初始化仓库
git init
# 查看已关联的仓库
git remote -v
# 关联远程仓库
git remote add origin https://github.com/xxxx/xxxx.git
# 删除远程仓库
git remote remove origin
# 直接修改远程仓库
git remote set-url origin https://github.com/xxxx/xxxx.git
# 查看远程仓库的详细信息
git remote show
git remote show origin
# 查看远程仓库上的所有分支
git ls-remote <remote-name>
git clone
克隆一个远程仓库到本地。
shell
# git clone <远程仓库地址>
git clone http://github.com/xxx/xxx.git
# git clone <远程仓库地址> <本地目录名>
git clone http://github.com/xxx/xxx.git <project_name>
git branch
用于管理分支的命令。它允许你查看、创建、删除和重命名分支,以及列出项目中所有的分支。
shell
# 查看本地仓库所有分支
git branch
# 查看远程仓库所有分支
git branch -r
# 查看本地和远程仓库的所有分支
git branch -a
# 基于当前分支,新建一个分支
git branch <new_branch_name>
# 删除分支:被删除分支 --是-- 基于当前分支新建出来的,可用-d 或 -D
git branch -d <local_branch_name>
# 删除分支:被删除分支 --不是-- 基于当前分支新建出来的,只能使用 -D
git branch -D <local_branch_name>
# 删除远程分支
git push origin --delete <remote_branch_name>
# 重命名当前分支
git branch -m <new_name>
# 为指定分支改名
git branch -m <old-branch-name> <new-branch-name>
# 建立追踪关系,在现有分支与指定的远程分支之间
git branch --set-upstream [branch] [remote-branch]
# 将本地分支与远程分支解绑
git branch --unset-upstream
git checkout
用于切换分支、提交和文件状态的命令。
shell
# 切换到本地分支
git checkout <local_branch_name>
# 切换到指定某次提交的commit_id
git checkout <commit id>
# 从现有分支中新建新的分支,并切换到新分支
git checkout -b <new_branch_name>
# 从远程分支中新建新的分支,并切换到新分支
git checkout -b <new_branch_name> origin/<remote_branch>
# 放弃工作区的修改,只影响工作区
git checkout .
# 放弃工作区和暂存区的修改,影响工作区和暂存区
git checkout -f
# 将指定文件从暂存区复制到工作区,用来丢弃工作区对该文件的修改
git checkout -- <file-name>
# 还可以指定从某个 commit 恢复指定文件,这会同时改变暂存区和工作区
git checkout HEAD~ -- <filename>
# -p 参数表示进入交互模式,只恢复部分变化
git checkout -p
# 切换到某个tag
git checkout tags/1.1.4
# 或者
git checkout 1.1.4
git switch
用于更轻松地切换分支。它是为了替代传统的 git checkout
命令,使分支切换更加直观和安全。
shell
# 切换到已存在的分支
git switch <old_branch_name>
# 创建并切换新分支,可以使用 -c 或 --create
git switch -c <new_branch_name>
# 切换到标签(tag)
git switch v1.0
git status
用于查看工作区和暂存区的状态。它会显示当前分支的信息以及工作目录中的未跟踪文件、已修改文件和已暂存文件的状态。
shell
# 查看工作区和暂存区的状态
git stataus
On branch main
Your branch is up to date with 'origin/main'.
git add
将工作区的修改添加到暂存区。
shell
# 将工作区的所有修改提交到暂存区
git add .
# 将指定目录添加到暂存区,包括子目录所有修改
git add [dir]
# 将src目录下的所有js文件添加到暂存区
git add src/**/**.js
git rm
用于删除文件或目录的命令。它会从你的工作目录中删除文件,并将删除操作记录在 Git
的提交历史中。
shell
# 删除单个文件
git rm <file-name>
# 删除整个目录(包括其中的所有文件和子目录),可以使用 -r 或 --recursive 选项
git rm -r <directory-name>
# 强制删除文件而不需要确认,可以使用 -f 或 --force 选项
git rm -f <file-name>
# 删除文件但保留本地副本
git rm --cached <file-name>
git commit
将暂存区的修改,提交到本地仓库。
git commit -m
与 git commit -am
的区别
-m
:是将暂存区的修改,提交到本地仓库。适用于部分文件更改需要单独跟踪的情况。-am
:将暂存区的修改提交到本地仓库之前,多了一步操作:先把本地的变动提交到暂存区,所以它是将暂存区和工作区的修改,提交到本地仓库。这种方式适合于只修改已跟踪文件并立即提交的情况,省去了手动使用git add
命令的步骤。
需要注意的是,
git commit -am
不会自动将未跟踪的文件添加到暂存区,对于未跟踪文件,你仍然需要手动使用git add
命令。如果有新文件需要添加到仓库,可以使用git add .
命令来添加所有未跟踪文件。
注意: 这里需要注意一点,工作区提交到暂存区的变动文件,是已经与远程版本库有了关联的(即之前已经提交到远程的),该命令对新增的文件,是不起作用的,所以提交新增的文件,需要执行git add .
指令。
shell
# 将暂存区的修改,提交到本地仓库
git commit -m '提交信息'
# 将暂存区和工作区的修改,提交到本地仓库
git commit -am '提交信息'
# 避开钩子函数的检查,强制提交
git commit -m '提交信息' --no-verify
git commit -m '提交信息' -n
# 将暂存区的修改,加到上一次的commit中,进入commit编辑,输入 :wq 退出
git commit --amend
# 修改上一次提交的commit信息(未push到远程仓库)
git commit --amend --only -m '新的提交信息'
# 重做上一次commit,并包括指定文件的新变化
git commit --amend <file1> <file2> ...
git pull/push 拉取/提交
拉去远程仓库分支到本地仓库,或者推送本地仓库分支到远程分支。
shell
# 拉取代码,将远程仓库分支同步到本地
git pull
# 将本地仓库的分支推送到远程分支(建立在本地分支追踪远程分支基础上)
git push
# 推送到远程分支,并设置本地分支跟踪的远程分支
git push --set-upstream origin <remote_branch>
git push -u origin <remote_branch>
# 删除远程分支并将更改推送到远程仓库
git push origin --delete <remote_branch>
git pull
=git fetch
+git merge
,拉取最新的远程分支,然后将这个分支合并到另一个分支。
git merge 分支合并
合并本地仓库的其他分支某个分支到当前分支,产生的新的 commit
对象有两个父节点。
如果"指定分支"本身是当前分支的一个直接子节点,则会产生
fast-forward
合并,即合并不会产生新的节点,只是让当前分支指向"指定分支"的最新commit
。
shell
# 把本地仓库的某分支合并到当前分支
git merge <local_branch>
# 取消合并
git merge --abort
如果 merge request
过于频繁,那么在主分支上就会有很多的 merge commit
,会严重污染分支历史记录 ,如果很多人很多分支进行开发与 merge
,分支图就会变成泡面图:
git rebase 分支变基
用于修改提交历史的强大工具。它允许你将一系列提交(通常是当前分支上的提交)重新应用到另一个基础分支上,从而创建一个线性、整洁的提交历史。
参数说明:
shell
--autosquash:参数用于互动模式,必须与`-i`参数配合使用。它会使得以前通过 git commit --fixup 和 git commit --squash 提交的 commit,按照指定的顺序排列(实质是选择提交说明以以 fixup! 或 squash! 开头的 commit),即 --fixup 的 commit 直接排在它所对应的 commit 的后面。例如:
git rebase --interactive --autosquash <branch>
--continue:用于解决冲突以后,继续执行 rebase。例如:
git rebase --continue
-i:会打开互动模式,让用户选择定制 rebase 的行为。例如:
git rebase -i develop
# 或者
git rebase -interactive develop
常用命令:
shell
# 将当前分支的提交应用到另一个分支
git rebase <local_branch>
# 解决冲突并继续重放提交
git add <resolved-file>
git rebase --continue
# 使用交互式 rebase 来更精细地控制提交历史
git rebase -i <local_branch>
# 跳过当前的提交
git rebase --skip
# 中断 rebase 过程并返回到原始状态
git rebase --abort
reabse
操作通过给原始分支中的每个提交创建新的 commits
来重写项目历史记录,从而达到在主分支上线性提交的目的。
git merge 和 git rebase 的区别
我们有两个分支,master
分支和 test
分支,test
分支是基于 master
分支在B
处的提交节点创建的,在创建后 master
分支又经过迭代提交了两次,从C
到D
节点,test
分支也基于B
往前继续更新了两次,到了F
节点。两者从B
开始就走向了分叉。
git merge的实现方式:
这时如果我们想将 test
分支合并到 master
分支,通过 merge
是如何工作的呢?
shell
# 将分支切换到master分支
git checkout master
# 把test分支合并到master分支
git merge test
从图中可以看到,这里生成了一个新的提交 G
,是怎么生成的呢? merge
命令 它会把两个分支的最新快照(F、E
和 D、C
)以及二者最近的共同祖先(B
)进行三方合并,合并的结果是生成一个新的快照G
(并提交)。
git rebase的实现方式:
shell
# 将分支切换到master分支
git checkout master
# 把test分支合并到master分支
git rebase test
从图就可以看出和 merge
命令不同。
这里有个名词定义我们先简单说明一下:
test
:基分支、目标分支master
:待变基分支,当前分支当执行
rebase
操作时,git
会从两个分支的共同祖先开始提取待变基分支上的修改,然后将待变基分支指向基分支的最新提交,最后将刚才提取的修改应用到基分支的最新提交的后面。
我们结合具体例子来说明,当我们在 master (待变基分支)
上执行 git rebase test(基分支)
时,git
就会从两者的共同祖先 B
开始,提取 master
分支上的修改,也就是 C
,D
两个 commit
,提取到之后 git
会先保存起来,然后将 master
分支指向 test
分支最新提交的节点,也就是 F
节点,然后把提取到的 C
,D
接到 F
后面,在这个过程当中,会删除原来的 C
,D
的 commit
记录,生成新的C
,D
,虽然C
,D
和原来的C
,D
的 commit
的内容是一样的,但是 commit id
是不同的。
rebase
操作如果用一句话进行解释就是改变基底
。master
分支原来的基底是 A
,现在变成了以 test
分支最新的提交 F
做为新的基底了。
优缺点:
-
git merge
- 优点:不会破坏原分支的提交记录。
- 缺点:会产生额外的提交记录,并进行两条分支线的合并。
-
git rebase
- 优点:无需新增提交记录到目标分支,
reabse
后可以直接将对象分支的提交历史加到目标分支上,形成线性提交历史记录,更加直观。 - 缺点:不能在一个共享分支上进行
reabse
操作,会带来分支安全问题。
- 优点:无需新增提交记录到目标分支,
使用场景:
- 合代码到公共分支的时候使用
git merge
,书写正确规范的merge commits
留下记录。 - 合代码到个人分支的时候使用
git rebase
,可以不污染分支的历史提交记录,形成简介的线性记录。
总结:
merge
是一个合并操作,会将两个分支的修改合并在一起,默认操作的情况下会提交合并中修改的内容。merge
的提交历史记录了实际发生过什么,关注点在真实的提交历史上面。rebase
并没有进行合并操作,只是提取了当前分支的修改,将其复制在了目标分支的最新提交后面。rebase
操作会丢弃当前分支已提交的commit
,故不要在已经push
到远程,和其他人正在协作开发的分支上执行rebase
操作。merge
与rebase
都是很好的分支合并命令,没有好坏之分,使用哪一个应由团队的实际开发需求及场景决定。
git stash 本地存储
将工作区的改动(未 commit
),临时存储在本地。
shell
# 默认按stash的顺序命名: stash@{n}
git stash
#添加备注
git stash save 'message'
# 查看存储列表
git stash list
# 应用最近一次的stash
git stash apply
# 应用指定的那一条
git stash apply stash@{n}
# 应用最近一次的stash,随后删除该记录
git stash pop
# 删除stash的所有记录
git stash clear
git log 日志过滤
主要用于查看 Git
版本演变历史(也就是提交历史),同时根据追加的参数和选项不同,过滤出想要的结果。
参数说明:
shell
按数量过滤:
-n: 显示前 n 条记录
shortlog -n:按作者分类,过滤出前 n 条
按时间过滤:
--after=: 如 --after='2023-08-30',显示 2023-8-30 之后的提交记录(包含8-30当天)
--before=: 如:--before='2023-08-30', 显示 2023-8-30 之前的提交记录(不包含8-30当天)
before/after 是个相对时间,可以这么写:--after='a week ago', --after='yesterday'
按作者过滤:
--author=: 作者名不需要精确匹配,只需要包含就行了,可使用正则匹配
按commit信息过滤:
--grep='关键字': 过滤出记录中(commit提交时的注释)与关键字有关的记录
过滤merge commit:
--no-merges: 过滤出不包含 merge 的记录
---merges: 只过滤出包含 merge 的记录
-p:按补丁显示每个更新文件的差异,比下一条 --stat命令信息更全
--stat:统计出每次更新的修改文件列表, 及改动文件中 添加/删除/变动 的行数
--pretty=:使用其他格式显示统计信息,参数有点复杂,目前很少用到
常用命令:
shell
# 列出当前分支的版本历史
git log
# 查看所有的提交记录
git log -all
# 将记录一行一行的形式展示:简洁明
git log --oneline
# 记录以图形化的形式展示
git log --graph
# 显示每次更新的文件修改统计信息,会列出具体文件列表
git log --stat
# 展示前10条
git log -10
# 按作者分类,过滤出前10条
git shrtlog -10
# 过滤出 'xxx' 的前10条记录,不包括 merge的记录
git log --author='XXX' -10 --no-merges
# 过滤出 commit 提交的注释中 包含'feat'关键字的前10条记录,不包括merge 的记录
git log --grep='feat' -10 --no-merges
git reflog 查看日志
用于查看和管理你的引用日志(reflog
)。引用日志是一个记录了仓库中引用(如分支和 HEAD
)的历史变化的日志,它可以帮助你恢复已删除的分支、撤销不小心的重置操作等。
shell
# 查看引用日志(显示当前分支 HEAD 的引用日志)
git reflog
# 查看特定分支或引用的引用日志
git reflog <branch-name>
# 引用日志会显示每次操作的记录,包括提交、分支切换、重置等。每个记录都有一个唯一的哈希值(commit hash),以及与之关联的描述信息,描述信息通常包括操作类型和相关提交的哈希值。如下所示:
b5e1c23 (HEAD -> main, origin/main) HEAD@{0}: commit: Update README
5ca8fd7 HEAD@{1}: reset: moving to HEAD
23456ab HEAD@{2}: commit: Fix a bug
git revert 代码撤销
撤销指定的提交,并产生一个新的 commit
表示撤销操作,但保留了原来的 commit
记录。
shell
# 撤销指定的提交版本
git revert <commit_id>
# 撤销的版本范围
git revert <commit_id1>..<commit_id2>
# 撤销上一次提交
git revet HEAD
# 撤销上上次提交
git revet HEAD^
git reset 代码回滚
让代码回滚到指定的提交版本,并且不保留原来的 commit
记录。
git reset
是Git
中用于移动当前分支的HEAD
指针的命令,它可以将分支回滚到指定的提交,并可以选择是否删除回滚的提交历史。git reset
有三种模式:--soft
、--mixed
(默认)、--hard
,它们分别用于不同的回滚场景。
参数说明:
shell
--soft:不改变工作区和缓存区,只移动 HEAD 到指定 commit
--mixed:只改变缓存区,不改变工作区。这是默认参数,通常用于撤销 git add
--hard:改变工作区和暂存区到指定 commit。该参数等同于重置,可能会引起数据损失。git reset --hard 等同于 git reset --hard HEAD
-p:表示进入交互模式,指定暂存区的哪些部分需要撤销。
常用命令:
shell
# 仅是撤销commit记录,所有改动都保留(工作区和暂存区),HEAD^ 代表上个版本
git reset --soft HEAD^
git reset --soft commit_id
# 撤销commit记录,不保留改动,直接回退到指定的提交版本
git reset --hard HEAD^
git reset --hard commit_id
# 连续撤销三个 commit:HEAD, HEAD^, and HEAD~2
git reset --hard HEAD~3
# 强推到远程
git push origin <branch> --force
# 如果不指定回滚的位置,那么等同于撤销修改
# 撤销上一次向暂存区添加的所有文件
git reset
# 无任何效果
git reset --soft
# 同时撤销暂存区和工作区的修改,回复到上一次提交的状态
git reset --hard
# 撤销上一次向暂存区添加的某个指定文件,不影响工作区中的该文件
git reset -- <filename>
注意事项:
- 使用
git reset --hard
可能会导致数据丢失,因为它会永久删除回滚点之后的提交历史和更改。在使用时务必谨慎,并确保已备份重要数据。 - 使用
git reset
回滚后,如果需要撤销回滚,可以使用git reflog
命令查看历史操作日志,并通过git reset <commit>
或git reset HEAD@{n}
恢复到之前的状态。
git revert 和 git reset 的区别
git revert 作用:
git revert
用于撤销某个提交的更改,并生成一个新的提交来表示撤销操作。它不会删除提交历史,而是将撤销操作作为一次新的提交保存在历史记录中。
git revert 使用场景:
适用于回滚公共历史和共享的分支,特别是当代码已经被推送到远程仓库,并且其他人可能已经基于该提交做了其他工作。使用 git revert
可以保持代码库的完整性,不会影响他人的工作。
git reset 作用:
git reset
用于移动当前分支的 HEAD
指针,可以将分支回滚到指定的提交,并且可以选择是否删除回滚的提交历史。它会将分支回滚到指定的提交,覆盖之后的提交,并将回滚的提交标记为未跟踪状态。
git reset 使用场景:
- 当需要撤销未推送的本地提交,且保留回滚的更改为未提交状态时,使用
git reset --soft
。 - 当需要撤销未推送的本地提交,但不保留回滚的更改时,使用
git reset --mixed
。 - 当需要回滚本地的所有更改,包括已提交和未提交的更改,使用
git reset --hard
。慎用git reset --hard
,因为它会永久删除回滚点之后的提交历史和更改,可能会导致数据丢失。在使用时务必谨慎,并确保已备份重要数据。
git tag 版本号管理
shell
# 列出所有标签
git tag
# 默认在 HEAD 上创建一个标签
git tag v1.0.0
# 指定一个 commit id 创建一个标签
git tag v1.0.0 <commit_id>
# 创建带有说明的标签,用 -a 指定标签名,-m 指定说明文字
git tag -a v1.0.0 -m "说明文字"
# 查看单个标签具体信息
git show <tagname>
# 推送指定的本地标签到远程仓库
git push origin <tagname>
# 推送本地未推送的所有标签到远程仓库
git push origin --tags
# 删除本地标签
git tag -d v1.0.0
# 删除一个远程标签
git push origin tag --delete <tagname>
git fetch
用于从远程仓库获取(拉取)最新提交和分支信息的命令,但不会将这些更改合并到当前工作分支。它通常用于更新本地仓库的远程分支引用和查看远程仓库的最新状态,以便你可以查看、比较和决定如何集成这些更改。
shell
# 从远程仓库中获取最新的提交和分支信息,默认情况下,它会拉取远程仓库中所有的分支信息,但不会合并到当前分支
git fetch
# 下载远程仓库的所有变动
git fetch [remote]
git cherry-pick
用于选择并将指定的提交复制到当前分支。它通常用于从一个分支中选择特定的提交并将其应用到另一个分支上,从而可以选择性地合并提交历史。
shell
# 指定要复制的提交的哈希值,并在当前分支上应用这些提交
git cherry-pick <commit-hash>
# 复制多个提交
git cherry-pick <commit-hash-1> <commit-hash-2> <commit-hash-3>
# 复制一个范围的提交,可以使用 .. 符号来表示范围
git cherry-pick <start-commit-hash>..<end-commit-hash>
# 解决冲突并提交
git cherry-pick --continue
# 取消复制
git cherry-pick --abort
注意事项:
git cherry-pick
会将指定提交的更改应用到当前分支上,但不会复制提交的作者和提交日期等信息。此外,它会创建新的提交,具有不同的哈希值。- 谨慎使用
git cherry-pick
,特别是在多人协作项目中。复制提交可能导致提交历史的混乱,因此建议在合并分支或从一个分支获取单个提交时使用。
git diff
用于比较文件或提交之间差异的命令。它可以帮助你查看代码、配置文件或提交之间的更改,并提供详细的比较信息。
shell
# 查看工作区与暂存区的差异
git diff
# 查看某个文件的工作区与暂存区的差异
git diff file.txt
# 查看工作目录中的修改与暂存区的不同
git diff --cached
# 查看两个commit的差异
git diff <commitBefore> <commitAfter>
# 查看工作区与上一次commit之间的差异,即如果执行 git commit -a,将提交的文件
git diff HEAD
# 查看工作区与某个 commit 的差异
git diff <commit>
# 显示两次提交之间的差异
git diff [first-branch]...[second-branch]
# 查看工作区与当前分支上一次提交的差异,但是局限于test文件
git diff HEAD -- ./test
# 查看当前分支上一次提交与上上一次提交之间的差异
git diff HEAD -- ./test
# 生成patch
git format-patch master --stdout > mypatch.patch
# 比较当前分支和 <branch_2> 分支之间的差异
git diff <branch_2>
# 比较两个不同分支之间的差
git diff <branch_1> <branch_2>
# 与上一条命令相同
git diff <branch_1>..<branch_2>
git show
用于查看提交详细信息的命令。它允许你查看单个提交的详细内容,包括提交信息、作者、提交时间以及提交的更改内容。
shell
# 显示提交信息,包括提交者、提交时间和提交消息
git show
# 输出某次提交的元数据和内容变化
git show <commit_id>
# 查看某次提交中的某个文件的差异
git show <commit_id> <file.txt>
# 使用 --patch 或 -p 选项,可以查看提交的补丁,以便更详细地了解每个更改
git show -p <commit_id>
# By revision
git show 12a86bc38
# By tag
git show v1.0.1
# By branch name
git show feature132
# Parent of a commit
git show 12a86bc38^
# Grandparent of a commit
git show 12a86bc38~2
# Time relative
git show feature132@{yesterday}
git show feature132@{2.hours.ago}