【Java】Git的一些常用命令

Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。我在工作中使用的版本控制软件也是Git,因此分享一下记录的一些Git常用命令。

Git常用命令

查询git版本

sh 复制代码
git -v

设置用户名

sh 复制代码
git config --global user.name <用户名> // 全局配置,所有仓库生效
           --system user.name <用户名> // 系统配置,对所有用户生效
          (省略(Local))user.name <用户名> // 本地配置,只对本地仓库有效,即只对当前的git仓库有效

设置邮箱地址

sh 复制代码
git config --global user.email <email address>

保存用户名和密码

sh 复制代码
git config --global credential.helper store

查看配置(显示全部配置信息)

sh 复制代码
git config -l

查看system配置

sh 复制代码
git config --system --list

查看global配置

sh 复制代码
git config --global --list

创建仓库

方法1: 初始化新的仓库

sh 复制代码
git init
git init <目录名> # 表示在该目录下初始化仓库

方法2: 从远程克隆一个仓库

sh 复制代码
git clone <仓库地址>

将添加到暂存区的文件取消暂存(即撤销git add操作)

sh 复制代码
git rm --cached <file>

提交文件到本地仓库(只会提交暂存区重点文件)

sh 复制代码
git commit -m '<提交的备注>' # -m: 用来添加提交信息,如果不加该参数,则会进入交互式状态,使用vim进行编辑
git commit -am # 用于提交跟踪过的文件,并附带一条提交信息,相当于"git add <file> + git commit -m <command>"

修改最后一次提交的记录

sh 复制代码
git commit --amend # 可以添加、删除或修改最后一次提交的内容

需要先将要修改的文件添加到暂存区,然后再执行该命令,之后系统会打开一个编辑器让你修改提交信息,如果只是添加文件而不需要修改提交信息,可以使用git commit --amend --no-edit

查看仓库提交历史记录

sh 复制代码
git log
git log --oneline # 查看简洁的提交记录

查看状态

sh 复制代码
git status
git status -s
?? temp/ # 该行 是查询结果,第一个"?"表示暂存区的状态,第二个"?"表示工作区的状态

回退版本,退回到某个提交的状态

sh 复制代码
git reset HEAD^	# 回退到上一个版本(对应 git reset --mixed HEAD^)

# git reset的三种模式
git reset --soft	# 回退到某个版本并保留工作区和暂存区的所有修改内容
git reset --hard	# 回退到某个版本并丢弃工作区和暂存区的所有修改内容
git reset --mixed	# 回退到某个版本并只保留工作区的修改内容,丢弃暂存区的修改内容(默认)

误操作了git reset怎么办?

  1. 查看操作的历史记录:git reflog
  2. 找到误操作之前的版本号
  3. 再使用git reset 回退到这个版本

查看暂存区的文件

sh 复制代码
git ls-files # 列出当前git仓库中跟踪的文件

对比差异

sh 复制代码
git diff # 默认比较的是工作区和暂存区的差异内容

git diff HEAD # 比较工作区和版本库之间的差异

git diff --cached # 比较暂存区和版本库之间的差异

git diff <版本ID1> <版本ID2> # 比较两个版本之间的差异

git diff HEAD HEAD~ # 比较当前版本和上一个版本的差异,HEAD~ / HEAD^ 均表示上一个版本

git diff HEAD~3 HEAD xxx.txt # 查看具体某个文件的差异(提交前的三个版本和当前版本比较)

git diff <branch_name> <branch_name> # 比较两个分支之间的差异

说明:

git diff 后面不加任何参数时,显示发生更改的文件及更改的详细信息:

  1. 第一行会提示哪些文件发生了变更;
  2. 第二行:git会将文件的内容使用哈希算法生成一个40位的哈希值,第二行只显示哈希值的前七位,后面的6位数字表示文件的权限
  3. 再往下就是修改的内容,红色表示删除的内容,绿色表示添加的内容。

如下图所示:

删除文件

4种方法:

  1. 直接删除后提交
sh 复制代码
rm <fileName> # 该命令是Linux命令,删除的是本地仓库(工作区)的文件
git add <fileName> # 删除暂存区中的该文件
  1. 将工作区和暂存区指定的文件都删除
sh 复制代码
git rm <filename>
  1. 把文件从暂存区删除,但保留在当前工作区中
sh 复制代码
git rm --cached <fileName>
  1. 递归删除某个目录下的所有子目录和文件
sh 复制代码
git rm -r *

注意事项:删除后不要忘记提交,否则版本库中仍存在该文件

查看所有分支列表

sh 复制代码
git branch

查看远程分支列表

sh 复制代码
git branch -r

创建新分支

sh 复制代码
git branch <分支名>

切换到不同的分支下

sh 复制代码
git checkout <分支名>

说明:该命令除了用于切换分支外,还可以用来恢复文件或目录到之前的某一个状态。如果分支名和文件名相同时会出现歧义,git checkout命令会默认切换分支,而不是恢复文件。

为避免这种歧义,git官方在2.23版本开始提供一个新命令:

sh 复制代码
git switch # 专门用来切换分支,推荐使用

恢复文件/目录到之前的某一个状态的用法

方法1: 使用git checkout命令

  1. 恢复文件到最近一次的提交状态
sh 复制代码
git checkout -- <文件名>

例如,要恢复名为demo.txt的文件到最近一次提交的状态,可以使用:

sh 复制代码
git checkout -- demo.txt
  1. 恢复目录到最近一次的提交状态
sh 复制代码
git checkout -- <目录名>/*

例如,要恢复名为project的目录到最近一次提交的状态,可以使用:

sh 复制代码
git checkout -- project/*

方法2: 使用 git restore 命令(Git 2.23及以上版本)

从Git 2.23版本开始,git restore命令被引入作为git checkout的替代品。它提供了一种更明确的方式来恢复文件。

  1. 恢复文件:
sh 复制代码
git restore <文件名>

例如,要恢复demo.txt文件:

sh 复制代码
git restore demo.txt
  1. 恢复指定目录中的所有文件
xml 复制代码
git restore <目录名>/*

例如,要恢复project目录中的所有文件:

复制代码
git restore project/*

方法3: 使用 git reset 命令

如果要恢复到某个特定的提交状态(不仅仅是最近的提交),可以使用git reset命令,这会将HEAD指向那个提交,并且可以有选择地修改工作目录和暂存区。

  1. 恢复到特定提交:

(1)找到想要回退到的提交的哈希值(commit hash)(可以使用git log来查看提交历史)。

(2)使用以下命令:

sh 复制代码
git reset --hard <commit-hash>

这会重置HEAD到指定的提交,并且工作目录和暂存区也会匹配那个提交的状态。注意,--hard选项会丢失当前工作目录中的所有更改

如果只是想查看更改而不实际重置,可以先试验不带--hard的命令:

perl 复制代码
git reset <commit-hash>

这会重置HEAD到指定的提交,但不会改变工作目录和暂存区的内容。可以先查看更改(使用git diff),确认无误后再使用--hard选项。

⚠️ 说明:

  • 使用--hard选项时要小心,因为它会丢失当前的工作目录更改。确保自己已经备份了重要数据或者确认不需要这些的更改了。
  • 如果不确定具体的提交哈希,可以先运行git log查看提交历史。
  • 在执行这些操作之前,最好先运行git statusgit diff来了解当前的更改状态。

创建新分支并切换到该分支

sh 复制代码
git checkout -b <分支名>

合并分支 & 变基分支

sh 复制代码
git merge <分支名> # 合并分支,merge后面的分支名是要被合并的分支,当前所在的分支是合并后的目标分支
git rebase <分支名> # 变基分支,在执行rebase中,git会先找到当前分支和目标分支的共同祖先,再把当前分支上"从共同祖先到最新提交记录的所有提交"都移动到目标分支的最新提交后面,其中目标分支为rebase后面跟的分支名

说明:

  • 两个分支没有修改同一个文件的同一处位置:git自动合并
  • 两个分支修改了同一个文件的同一处位置:产生冲突

解决方法:

  1. 手动修改冲突文件,合并冲突内容
  2. 添加暂存区:git add file
  3. 提交修改:git commit -m 'message'
  4. 当不想继续执行合并操作时中止合并过程:git merge --abort # 中断合并

merge和rebase的异同:

markdown 复制代码
- merge
	优点:不破坏原分支的提交记录,所有提交记录和合并历史都会保留下来,方便后续的查看和回滚。
	缺点:会产生额外的提交记录和两条分支线的合并,使提交记录变复杂。

- rebase
	优点:不需要新增额外的提交记录到目标分支,形成一个线性的提交历史记录,直观且干净。
	缺点:会改变提交历史,需要避免在一个共享分支上进行rebase操作。

查看分支图

sh 复制代码
git log --graph --oneline --decorate --all

将以上命令定义一个别名使用:

sh 复制代码
alias graph="git log --graph --oneline --decorate --all"

删除分支

sh 复制代码
git branch -d <分支名> # -d: 删除已经完成合并的分支
git branch -D <分支名> # -D: 强制删除未合并的分支
git push origin --delete <分支名> # 删除远程分支

Git的一些其他知识点补充

git的工作区域

  1. 工作区(Working Directory):工作目录/本地工作目录(即.git所在的目录)
  2. 暂存区(Staging Area/Index):临时存储区域,保存即将提交到git仓库等修改内容(即.git/index)
  3. 本地仓库(Local Repository):git init的仓库目录(即.git/objects)

三者关系:开发完后,工作区的内容 git add -> 暂存区 git commit -> 本地仓库

git的文件状态

  1. 未跟踪(Untracked):新创建的还没有被git管理的文件(文件显示为红色),不参与版本控制。可以通过git add命令将该状态变为Staged
  2. 未修改(Unmodified):文件已经入库,已经被git管理,但文件内容没有发生变化,即版本库中的文件快照内容和文件夹中完全一致。如果该类型文件被修改,则变成Modified,如果使用git rm从版本库移除,则变成Untacked文件
  3. 已修改(Modified):已经修改过的文件,但还没有添加到暂存区中。通过git add可进入Staged状态;使用git checkout切换分支则丢弃修改的内容,从而返回到Unmodified状态,其中git checkout命令从库中取出文件并覆盖当前修改
  4. 已暂存(Staged):已修改后添加到暂存区的文件(文件显示为绿色)。执行git commit则将修改的内容同步到库中,此时库中的内容和本地文件又变为一致,文件为Unmodified状态。可以执行git reset HEAD <filename>取消暂存,文件状态变为Modified

以上文件状态的关系:Untrack -> git add -> Unmodified -> 修改文件 -> Modified -> git add -> Staged

GitHub的使用和远程仓库操作

1. 创建/推送一个仓库

  • 在命令行上创建一个新仓库:
sh 复制代码
echo "# remote-repo" >> READ.md
git init
git add READ.md
git commit -m "first commit"
git branch -M master
git remote add origin [email protected]:<仓库地址>/<仓库名.git>
git push -u origin master
  • 从命令行推送一个已存在的仓库:
sh 复制代码
git remote add <远程仓库别名> [email protected]:<仓库目录>/<仓库名.git>
git branch -M master # 指定分支的名称为master
git push -u origin master # 把本地的master分支和远程origin仓库的master分支关联起来,其中,-u是upstream的缩写,以上全写:git push -u origin master:master(本地仓库的分支和远程仓库的相同的话,可以略写本地仓库的分支名)
git remote -v # 查看当前仓库所对应的远程仓库的别名和地址
origin [email protected]:<仓库目录>/<仓库名.git>	# origin:本地仓库对应的远程仓库别名

2. 使用ssh方式登陆需要配置ssh密钥

  1. 进入~/.ssh目录,执行ssh-key generate -t RSA -b 4096(生成SSH密钥, -t RSA: 指定协议为RSA; -b 4096: 指定生成的大小为4096)
  2. 回车后提示需要输入密钥的文件名称,eg.test(不指定的话,默认在.ssh目录下生成名为id_rsa的密钥文件)
  3. 输入密钥文件名称回车后,生成一个test(私钥文件)和一个test.pub(公钥文件,可上传至GitHub)
  4. 如果密钥文件是指定的名字,则需要再增加一个步骤:添加一个config文件,如下所示(表示在访问github.com时,指定使用test密钥文件)
sh 复制代码
# github
Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/test

3. 本地仓库和远程仓库保持同步(pull 和 push命令)

sh 复制代码
git push <remote> <branch>
git pull <远程仓库名> <远程分支名>:<本地分支名> # 作用:把远程仓库的指定分支拉取到本地分支再进行合并
git pull # 以上命令的简写版,表示拉取仓库别名为origin的master分支(高版本的是main)

默认分支名从master改为main的历史原因:由于master这个词带有种族歧视的含义,因此在后来的git高版本中更名为main。

注意点:执行完git pull之后,git会自动执行一次合并操作,如果远程仓库和本地仓库的修改内容没有冲突,则可以合并成功,否则由于冲突导致失败,需要手动解决冲突。

从远程仓库获取内容还可以使用fetch命令(只获取远程仓库的修改,不自动合并到本地仓库中,需要手动合并)

.gitignore文件的介绍

作用:可以忽略掉一些不应该加入到版本库中的文件。

生效的前提:文件不能是已经被添加到版本库中的文件。

应该忽略哪些文件:

  1. 系统/软件自动生成的文件
  2. 编译产生的中间文件和结果文件(eg.Java编译生成的.class文件)
  3. 运行时生成的日志文件、缓存文件、临时文件
  4. 涉及身份、密码、口令、密钥等敏感信息文件

.gitignore文件的匹配机制:

  1. 从上到下逐行匹配,每一行表示一个忽略模式
  2. 空行或者以#开头的行都会被git忽略(一般空行用于可读性的分隔,#一般用作注释)
  3. 使用标准的Blog模式匹配,例如:
text 复制代码
	* 通配任意个字符
	? 匹配单个字符
	[] 表示匹配列表中的单个字符,例如[abc]表示a/b/c
  1. ** 表示匹配任意的中间目录
  2. \] 可以使用短中线连接,例如:\[0-9\]表示任意一位数字,\[a-z\]表示任意一位小写字母

举例:

text 复制代码
*.a # 忽略所有.a文件

!lib.a # 在以上基础上,即使忽略了所有的.a文件,但跟踪所有的lib.a文件

/TODO # 只忽略当前目录下的TODO文件,不忽略subdir/TODO

build/ # 忽略任何目录下名为build的文件夹

doc/*.txt # 会忽略doc/note.txt,但不会忽略doc/server/note.txt

doc/**/*.pdf # 忽略doc/目录及其所有子目录下的.pdf文件

良好的习惯和规范

分支命名(推荐使用有意义的描述性名称命名分支)

  1. 版本发布分支/Tag示例:v1.0.0
  2. 功能分支示例:feature-login-page
  3. 修复分支示例:hotfix-#issueid-desc

分支管理:

  1. 定期合并已成功验证的分支,及时删除已经合并的分支
  2. 保持合适的分支数量
  3. 为分支设置合适的管理权限

Git和SVN最主要区别

  1. SVN是集中式版本控制系统(必须联网才能工作,对网络带宽要求较高),版本库集中放在中央服务器中,工作时使用自己的电脑,需要先从中央服务器得到最新版本再工作,完成工作后,需要把代码推送到中央服务器。
  2. Git是分布式版本控制系统,没有中央服务器,每个人的电脑就是一个完整的版本库,工作时不需要联网(因为版本都在自己电脑上)。协同的方法示例:自己在电脑上改了fileA,其他人也在电脑上改了fileA,此时只需要把各自的修改推送给对方,就可以互相看到对方的修改了。

Git是目前世界上最先进的分布式版本控制系统。

【扩展】ls -altr

sh 复制代码
ls -altr
    # -a: 展示目录中的所有文件,包括隐藏文件
    # -l: 展示每个文件的详细信息(文件权限、链接数、所有者名称和组所有者、文件大小、最后修改的时间和文件/目录名称等)
    # -t: 对最后修改日期和时间进行排序
    # -r: (和-t连用)基于日期和时间逆向排序
相关推荐
加瓦点灯5 分钟前
什么?工作五年还不了解SafePoint?
后端
飞翔的猪猪1 小时前
GitHub Recovery Codes - 用于 GitHub Two-factor authentication (2FA) 凭据丢失时登录账号
前端·git·github
他日若遂凌云志1 小时前
Lua 模块系统的前世今生:从 module () 到 local _M 的迭代
后端
David爱编程1 小时前
Docker 安全全揭秘:防逃逸、防漏洞、防越权,一篇学会容器防御!
后端·docker·容器
小码编匠1 小时前
WinForm 工业自动化上位机通用框架:注册登录及主界面切换实现
后端·c#·.net
weixin_483745621 小时前
Springboot项目的目录结构
java·后端
阿里云云原生1 小时前
2025年第二届“兴智杯”智能编码创新应用开发挑战赛正式启动
后端
保持学习ing2 小时前
SpringBoot 前后台交互 -- CRUD
java·spring boot·后端·ssm·项目实战·页面放行
ShiShuoMing2 小时前
前后端分离项目单机部署
后端
noodb软件工作室2 小时前
支持中文搜索的markdown轻量级笔记flatnotes来了
前端·后端