Git常用命令
# Git常用命令
# 概念
# 工作区和暂存区
和svn有很大的不同,Git中引入了暂存区/缓存区(Stage/Index)的概念
【工作区】——> 【暂存区/缓存区】——> 【本地仓库】
- 工作区很好理解,就是我们能看到的工作目录,就是本地的文件夹
- 这些本地的文件夹我们要通过git add 命令先将它们添加到 暂存区中
- git commit 命名则可以将暂存区中的文件提交到本地仓库中
# 基本操作
git init
# 初始化仓库
# 执行完成后当前目录下会多出一个 .git 的隐藏文件夹,所有 git 需要的数据和资源都存放在该目录中
git status
git branch
git add file.txt
git add ./*
git commit -m "message"
# edit commit
git commit --amend
git log
git log --pretty=short
git log --pretty=oneline
git log file.txt
git log -p file.txt
git diff
git diff head
//压缩提交历史
git rebase -i
# 命令可以实现提交历史的压缩。比如我们在开发某一个功能时,提交了很多次,当所有功能都写完时,想将这些提交压缩为一个,就可以使用该命令
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# git log 的特殊情况
有时输入 git log 后,会出现 : (冒号)
原因:运用 git commit 命令提交信息数量增多,且你当前窗口没有铺满全屏
解决方案:
- 按
上下方向键或者鼠标滑轮查看更多未展现的提交信息 - 按
q、Q、ZZ直接退出该查看模式
# git commit --amend
amend:修正修订的意思
git commit --amend这个命令就可以这么理解:对之前的commit 提交进行修改。事实上确实如此,不仅可以修改提交的内容,还可以修改commit 信息。
注意:这里的之前指最近的commit,而且没有push到远程。
修改提交的内容分为2种情况:
- 提交了代码之后,又有新的改动,不想创建两个commit
- 发现一个地方改错了,下次提交时不想保留上一次的记录
这时就可以使用git commit --amend命令把新的内容添加到之前的commit里面,这个命令没有添加新的提交,而是用新提交取代了原始提交。
如果我们要写的备注非常多,我们可以直接执行 git commit 命令,此时会自动打开一个 vi 编辑器,我们直接在编辑器中输入备注信息即可。假设我在 git01.txt 中随意添加一行内容,然后依次执行 git add、git commit 命令,此时系统会自动打开一个 vi 编辑器 编写完毕备注信息后,直接保存即可
# 各种撤回操作
# working space 撤销工作区
git checkout -- <file> # eg. git checkout -- file.txt
git checkout -- . # eg. 所有文件都会撤销
# stage space 撤销暂存区
git reset head
git checkout -- <file.txt>
# 撤销提交到本地仓库的代码
git reset --hard <版本号>
# eg. 命令回到回退之前的状态:
git reset --hard 695ce1fe
git reset --hard HEAD~1
git reset HEAD^^ 向前回退2个版本
2
3
4
5
6
7
8
9
10
11
12
13
14
1.可以使用 HEAD^ 来描述版本,一个 ^ 表示前一个版本,两个 ^^ 表示前两个版本,以此类推。
2.也可以使用数字来代替 ^ ,比如说前 100 个版本可以写作 HEAD~100 。
3.也可以直接写版本号,表示跳转到某一个版本处。我们每次提交成功后,都会生成一个哈希码作为版本号,所以这里我们也可以直接填版本号,哈希码很长,但是我们不用全部输入,只需要输入前面几个字符即可,就能识别出来。
# 分支合并 merge跟rebase
git branch
# 列出分支几基本命令,没有参数时 列出本地分支
git checkout testing
git checkout -b testing
git branch -d testing # delete branch
git branch -r # 查看远程所有分支
git branch -a #查看所有分支
git branch
git branch <branch name>
git checkout <branch name>
# 创建并切换分支
git checkout -b <branch name>
# 切换回上一个分支
git checkout -
# 将 fa 分支合并到 master 分支上。其中 –no-ff 表示强行关闭 fast-forward 方式,
# fast-forward 方式表示当条件允许时, git直接把 HEAD 指针指向合并分支的头,完成合并
# 这种方式合并速度快,但是在整个过程中没有创建 commit
# 所以如果当我们删除掉这个分支时就再也找不回来了,因此在这里我们将之关闭。
git merge --no-ff <target branch name> # - - no - ff 注意no前面是2个 -
# 注意使用之后 合并的分支 还是会存在 不会消失
# 可以使用 git branch -d test 命令来删除它。
# 但是请注意,只有当 test 分支已经被合并到其他分支或者已经被标记为可以删除时,
git branch -d <branch name>
# 在进行分支合并时 可能出冲突,这很正常,解决就是了,
进行 git merge
# 合并分支时如果出现冲突还是先重新编辑冲突文件,编辑完成之后,再执行
git add 和 git commit 即可。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 衍合概念图

git checkout experiment
git rebase master
----
git checkout master
git rebase experiment or git merge experiment
# 退回到之前的状态
git rebase --abort
// 或者解决完冲突
git add <file name>
git rebase --continue
2
3
4
5
6
7
8
9
10
11
rebase 的冲突需要一个一个解决,如果有十个冲突,得先解决完第一个,然后执行如下命令后才会出现第二个冲突,直到所有冲突解决完。而merge 是一次性将所有的冲突都显示出来。
rebase的分支,合并后,会消失掉,而merge的分支,合并后,仍会看到记录。
一般来说,不推荐使用rebase。
但为了让分支树看起来更简化,个人分枝偶尔也会选用rebase。这样可以线性的看到每一次提交,并且没有增加提交节点。 但这样会存在缺陷:公共分支上rebase会打乱且篡改提交记录,若别人想看该公共分支的历史提交记录,它看到的不是完整的历史记录。
# 关联远程仓库
git remote -v
git remote add origin <仓库地址>
# git remote add origin git@github.com:lenve/test.git
# 在上述这条命令中 git 会自动将远程仓库的名字设置为origin 方便后续操作
git remote set-url origin <仓库地址>
# 修改远程仓库别名为 origin 的地址
git remote rm <仓库别名>
git push -u origin master
/*
-u参数可以在推送的同时,
将 origin 仓库的 master 分支设置为本地仓库当前分支的 upstream(上游)。
添加了这个参数,将来运行 git pull 命令从远程仓库获取内容时,
本地仓库的这个分支就可以直接从 origin 的 master 分支获取内容,
省去了另外添加参数的麻烦。这个参数也只用在第一次 push 时加上,
以后直接运行 git push 命令即可。
*/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 推送到其它分支
git checkout <other branch name>
git push -u origin <other branch name>
2
先切换到其他分支例如: fa 分支,然后执行 git push 命令,参数含义和之前的一样,这里我们创建的远程仓库的分支名也为 fa(当然我们可以取任何名字,但是为了不混淆,最好取一致的名字)。这两条命令执行成功之后,此时在网页中我们就可以看到—此时的远程仓库中已经有多个分支了(多了fa分支)
# 从远程仓库获取
git clone <远程仓库地址>
# 获取指定分支
git checkout -b fa origin/fa
2
3
# 标签管理
我们可以针对某一次的提交打上一个标签,有点类似于给某次提交取个别名,比如 1.0 版本发布时打个标签叫 v1.0,2.0 版本发布时打个标签叫 v2.0 ,因为每次版本提交的结果都是一连串的哈希码,不容易记忆,打上 v1.0,v2.0 这些具有某种含义的标签后,可以方便我们进行版本管理。
# 查看当前仓库中的所有标签
git tag
# 创建标签很简单
git tag <tagname>
git tag v1 # 创建一个名为v1的tag,该tag默认是创建在最新的一个commit上
# 利用 git show <tagname> 来查看标签对应的版本信息
git show v1
# 删除
git tag -d <tagname>
# 给历史上的某次 commit 打一个标签呢?
# 我们可以通过如下命令 git tag <tagname> <commitversion>
git tag v0.0 7b23d
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 工作常用
工作中往往是多人一起开发,你可能会涉及到多个分支。你的本地也可能会有多个分支,那你就必须要了解切换以及暂存这个操作。
# 查看当前分支
git branch
# 查看本地所有分支 以及关联的远程分支
git branch -vv
# 列出远程分支
git branch -r
2
3
4
5
6
# 分支查看与切换
Git branch -vv 是我个人很常用的一个命令
用于详细查看本地所有分支及其与远程分支的关联状态。
以下是一个示例
$ git branch -vv
* main abc1234 [origin/main] Add login feature
develop def5678 [origin/develop: ahead 2] Fix bug in payment module
feature-x 123abcd [origin/feature-x: behind 1] Initial commit
2
3
4
# 拉取分支
本地分支你不想改,但此时你想新建一个分支,并从一个远程指定分支重新拉取代码,如何实现?
# 先确保本地有最新的远程分支信息
git fetch origin
# 假设你想基于远程的 feature/login 分支创建本地新分支 my-feature
git checkout -b my-feature origin/feature/login
2
3
4
5
Git 会做几件事:
- 连接远程仓库(如 origin);
- 下载远程所有最新的分支、标签、提交信息;
- 更新本地的远程分支引用(例如
origin/main、origin/develop等); - 不会改变你当前所在分支的内容(不会自动合并)。
举个例子:
假设你本地仓库状态是:
main ---- A --- B
origin/main ---- A --- B --- C --- D
# 执行后 :
git fetch origin
2
3
4
5
结果:
- 本地的
origin/main会更新到远程的最新节点 D; - 但你的
main分支依旧停留在 B; - 也就是说,Git 只是同步了远程分支的状态。
# 关联分支
如果本地分支未关联远程分支,该如何进行关联?
- 在创建分支时直接关联(推荐)
git checkout -b <本地分支名> --track origin/<远程分支名>
- 对已有本地分支手动设置上游(upstream)
git branch --set-upstream-to=<remote>/<remote-branch>
# 或者缩写形式(常用):
git branch -u <remote>/<remote-branch>
# eg.
# 假设当前在本地分支 dev,想关联 origin/dev
git branch --set-upstream-to=origin/dev dev
# 或简写(当前就在 dev 分支时):
git branch -u origin/dev
2
3
4
5
6
7
8
9
10
假设:
- 远程仓库名是
origin - 远程分支是
develop - 当前本地分支是
develop
那么你可以执行:
git branch --set-upstream-to=origin/develop
# 简写
git branch -u origin/develop
# 执行成功后,Git 会输出类似
Branch 'develop' set up to track remote branch 'develop' from 'origin'.
# 此时你就可以直接使用简化命令:
git pull
git push
# 以下2个是 上面2个的完整版
git pull origin develop
git push origin develop
2
3
4
5
6
7
8
9
10
11
12
13
14
# 推送分支
本地分支没关联远程分支,可以推送吗?
可以!
# 假设本地分支叫 feature-x,想推送到远程的 feature-x
git push origin feature-x
2
第一次推送后,Git 通常会提示你设置上游:
hint: use 'git push -u origin feature-x' to set upstream
如果加上 -u(即 --set-upstream),推送后会自动建立关联:
git push -u origin feature-x # 推送 + 关联
本地分支关联了远程分支 A,可以推送到远程分支 B 吗?
可以!Git 允许“推送到任意远程分支”,与当前跟踪的上游无关。
# 假设:
# - 本地分支 feature 关联了 origin/feature(A)
# - 但你想推送到 origin/experiment(B)
git push origin feature:experiment
# 语法解释:git push <远程名> <本地分支>:<远程分支>
# 左边是 本地分支,右边是远程分支
2
3
4
5
6
7
8
9
本地分支没关联任何分支,是否可以进行推送?
不可以!
# 执行git push 会报错
git push
fatal: The current branch xxx has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin xxx
2
3
4
5
6
7
推送时,本地分支需要进行关联远程分支才行,或者已经关联了才行。
推送本地的某个分支,但该分支名,远程分支没有,是否可以进行推送?
可以!
git push origin your-branch-name
#但此时仍然没有自动建立“上游关系”(upstream tracking)。
# 如果希望之后可以直接用 git push(不用每次写 origin 分支名),则加上:
git push --set-upstream origin your-branch-name
#简写为
git push -u origin your-branch-name
2
3
4
5
6
7
可以成功推送,Git 会自动在远程创建同名分支。
# stash
当你在使用 git checkout(或 git switch)切换分支时,如果 Git 提示 “本地有未提交的修改”(例如:error: Your local changes to the following files would be overwritten by checkout),说明你当前工作区有未提交的更改,而目标分支中这些文件的内容与你本地的修改冲突。
# 临时保存修改
如果你的修改还没准备好提交,但又想先切换分支,可以用 git stash 把当前修改“暂存”起来。
# 1. 暂存当前工作区和暂存区的修改
git stash push -m "临时保存:正在开发登录功能"
# 2. 切换分支(现在可以安全切换了)
git checkout other-branch
# 3. 后续想恢复修改时,回到原分支再弹出
git checkout original-branch
# 注意 stash pop 会删除stash记录
git stash pop # 或 git stash apply(保留stash记录)
2
3
4
5
6
7
8
9
10
11
# 相关操作
# 如果你想查看 stash 记录 ,则可以使用list
git stash list
# 输出:
# stash@{0}: On main: 临时保存:正在开发登录功能
# stash@{1}: On develop: 修复样式问题
# 可以用 git stash pop stash@{1} 恢复指定记录。
git stash pop stash@{1}
# apply 和 pop
git stash apply
git stash pop
# 删除 指定stash
git stash pop stash@{0}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
git stash apply 和 git stash pop 都是用来恢复之前用 git stash 保存的修改的命令,但它们在是否删除 stash 记录这一点上有关键区别。
| 命令 | 是否应用 stash | 是否删除 stash 记录 | 适用场景 |
|---|---|---|---|
git stash apply | 是 | 不删除(保留记录) | 想恢复修改,但保留 stash 备份(可重复使用或稍后清理) |
git stash pop | 是 | 删除(弹出记录) | 想恢复修改,并立即清理该 stash(一次性使用) |
其实,git stash pop=git stash apply+git stash drop
注意:
git stash apply,它默认恢复最新的stash
git stash apply # 应用最新 stash
git stash apply stash@{1} # 应用指定的 stash
2