Git 常用命令介绍

发布于 2023-05-04 21:30:36 字数 12343 浏览 65 评论 0

配图源自 Freepik

版本控制工具有很多,比如 CVS、SVNGit 等,但目前用得最广泛的应该就是 Git 了。

下面介绍一些常用的 Git 命令。

一、全局、本地必要配置

挺有必要的,会更清晰的跟踪提交者的信息。

# 全局配置
$ git config --global user.name "your_name"
$ git config --global user.email "your_email"

# 本地配置
git config user.name "your_name"
git config user.email "your_email"

二、初始化仓库

# 初始化
$ git init

# 与远程仓库建立连接
$ git remote add origin <repo_addr>

# 修改远程仓库地址(一)
$ git remote set-url origin <repo_addr>

# 修改远程仓库地址(二)
$ git remote rm origin
$ git remote add origin <repo_addr>

# 修改远程仓库地址(三)直接修改配置文件
$ vim .git/config

三、关于克隆仓库

$ git clone <repo_addr>

# 使用 dir_name 作为克隆仓库的目录名称
$ git clone <repo_addr> <dir_name>

以上方式仅会克隆仓库的「默认分支」,通过 git branch --list 能看到本地只有一个分支。

自 2020 年 10 月起,在 GitHub 平台新创建的仓库,其默认分支名称正式调整为 main详见)。如果本地通过 git init 创建的仓库,其默认分支仍是 master 的话,可通过命令调整默认分支:

$ git config --global init.defaultBranch main

如果再通过新建分支再拉取指定分支,甚至可能还需要解决冲突,太繁琐了。

那么,如何快速有效的直接克隆远程指定分支?

$ git clone -b <指定分支名> <远程仓库地址>

# 指定目录名称
$ git clone -b <指定分支名> <远程仓库地址> <dir_name>

比如,我远程有 masterdevelop 两个分支,通过 git clone -b develop git@github.com:toFrankie/git_dev_demo.git 会克隆 develop 分支到本地,而且本地只有 develop 一个分支。

*部分内容源自 Git 克隆远程仓库的指定分支

四、分支操作

4.1 列出所有分支

# 列出所有本地分支
$ git branch

# 列出所有远程分支
$ git branch -r

# 列出所有本地分支和远程分支
$ git branch -a

# 如果分支太多,可以使用模糊查找
$ git branch | grep 'branch-name'

4.2 新建分支

若分支已存在,以下命令都会失败。

# 新建分支,但不会切换至新分支
$ git branch <branch-name>

# 新建分支,并切换至该分支。
$ git checkout -b <branch-name>

# 根据已有分支创建新的分支
$ git checkout -b <branch-name> origin/<远程分支名称>
# 例如,创建一个远程 develop 分支的本地分支
# git checkout -b develop origin/develop

# 重命名本地分支名称
$ git branch -m <old-branch-name> <new-branch-name>

有时候,你可能需要取出某个历史版本,可以理解为基于某个 Commit 来创建一个新的分支,就能看到历史版本了。可以使用以下命令:

# 基于 <SHA1> 新建一个新分支
$ git checkout -b <branch-name> <SHA1>

# 若不打算修改,只是想 checkout 的话
$ git checkout <SHA1>

举个例子,我们有以下 Commit Log,我需要基于 1b90fceff0f3e4f16b1b850019573d3103b69a96 的历史版本,新创建一个分支:

4.3 合并分支

# 合并指定分支到当前分支
$ git merge <branch-name>

# 工作中,特性分支合并至主干分支,通常会使用以下这个
$ git merge --no-ff <branch-name>

--no-ff(not fast forward)的作用是:要求 git merge 即使在 fast forward 条件下也要产生一个新的 Merge Commit。采用 --no-ff 的方式进行分支合并目的在于:希望保持原有「特性分支」整个提交链的完整性。

关于分支合并,有使用 git merge 的,也有使用 git rebase 的,而且不同派别还很容易争吵起来。就像缩进是采用 Tab 好还是 Space 好的争论一样,那么实际中如何权衡,根据团队而定吧。

4.4 删除分支

# 删除本地指定分支
$ git branch -d <branch-name>

# 删除远程分支
git push origin --detele <branch-name>

# 删除远程分支(方法二:向远程分支推送一个空分支)
$ git push origin :<远程分支名>

4.5 重命名远程分支

要重命名远程分支名称,其实就是先删除远程分支,然后重命名本地分支,再重新推送一个远程分支的过程。

例如,将远程分支 dev 重命名为 develop,可以这样操作:

# 1. 删除远程分支 dev
$ git push origin --delete dev

# 2. 重命名本地分支 dev 为 develop
$ git branch -m dev develop

# 3. 推送本地分支 develop
$ git push origin develop

五、暂存提交推送

5.1 暂存更改

关于 git add 命令,需要注意一下 1.x 版本与之有些不同,最后有标注。

# 提交新文件(new file)、被修改(modified)文件以及被删除(deleted)文件。
$ git add .

# 提交新文件(new file)、被修改(modified)文件以及被删除(deleted)文件。
$ git add -A

# 提交被修改(modified)和被删除(deleted)文件,不包括新文件(new file)
$ git add -u

# 提交新文件(new file)和被修改(modified),不包括被删除(deleted)文件
$ git add --ignore-removal .

# 获取帮助
$ git add -h

# 以上为 2.x 版本的标准。
# 以下为 1.x 版本的区别之处:
# 1.x 的 `git add .` 不包括被删除文件(deleted)
# 1.x 不存在 `git add --ignore-removal .` 命令,但其作用等同于 1.x 版本 `git add .`

5.2 提交暂存

# 提交已暂存文件
$ git commit -m 'commit message'

# 提交已暂存文件,以及跟踪过但未被添加到暂存的文件
# 注意:git commit -am 可以写成 git commit -a -m,但不能写成 git commit -m -a
$ git commit -am 'commit message'

# 修改最后一次的提交说明(但 commitId 会改变哦,因为它是一次全新的提交)
$ git commit --amend

注意一下,git commit --amend 命令,只能修改最新一次的提交说明 ,执行命令进入 vim 模式(具体如何插入编辑,保存退出不展开赘述了,你们都会的)。亦可通过 git commit --amend -m 'Commit Message' 直接覆盖不用进入 vim 编辑器。

需要注意的是,该命令会导致 commitId(快照唯一标识)发生改变。可通过 git log(查看历史提交记录)前后对比发现。其实呢,修改过的提交实际上是全新的提交,而先前的提交将不再位于您当前的分支上。

该命令其实还有很多选项,还能更改提交文件等,想了解请看这里

5.3 推送至远程分支

主要用于将本地更新推送到远程主机,但不同简化形式、命令参数产生延申效果。

一般地,远程主机名 remote 都为 origin

# 不省略本地分支名和远程分支名情况下,冒号(:)前后是没有空格的
$ git push <远程主机名> <本地分支名>:<远程分支名>
# git push origin master:master

还有几种简化形式的写法:

  • 省略远程分支(多分支情况下,本人常用这种形式)
# 将本地分支推送到远程主机上的同名分支。如果远程分支不存在,则会自动创建一个远程分支。
$ git push <远程主机名> <本地分支名>
# git push origin master
  • (慎用)省略本地分支(相当于删除远程分支)
# 将一个“空的本地分支”推送至远程分支,即表示删除指定的远程分支。
$ git push <远程主机名> :<远程分支名>
# git push origin :master

# 等同于
$ git push origin --delete <远程分支名>
  • (不推荐)省略本地分支、远程分支
# 将当前分支推送至远程主机上的对应分支
$ git push <远程主机名>
# git push origin

这种形式要求当前本地分支和远程分支之间存在追踪关系。

怎么理解?

首先我不推荐,而且平常也不用这种形式的进行推送的。假如有存在 masterdevelop 两个分支,当与远程分支建立追踪关系的是 master 分支,那么处于 develop 分支时,使用 git push origin 形式推送至远程主机时就会提示:The current branch test has no upstream branch.,然后再执行 git push --set-upstream origin develop 即可使用这种形式的推送。

  • 省略远程主机、本地分支、远程分支
# 将当前分支推送至远程主机对应分支
$ git push

这种形式,除了要求当前本地分支和远程分支之间存在追踪关系之外,还要求当前当前分支只有一个追踪分支。

  • 省略远程分支,添加参数 -u
# 将本地分支推送到远程主机上的同名分支。如果远程分支不存在,则会自动创建一个远程分支。
$ git push -u <远程主机名> <本地分支名>
# git push -u origin master

这种形式适用于当前分支与多个主机存在追踪关系,可以利用 -u 指定一个默认的主机,这样后面就可以不加任何参数适用 git push 推送对应的分支了。

以上指令执行之后,在 .git/config 配置文件下会有分支的对应:

[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
	ignorecase = true
	precomposeunicode = true
[remote "origin"]
	url = git@github.com:toFrankie/git_dev_demo.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master
[branch "develop"]
	remote = origin
	merge = refs/heads/develop

六、标签操作

# 列出所有 tag
$ git tag

# 查看 tag 信息
$ git show <tag-name>

# 轻量标签
$ git tag <tag-name>

# 附注标签
$ git tag -a <tag-name> -m <message>
# 例如,打一个 v1.0.0 的标签
# git tag -a v1.0.0 -m 'v1.0.0 release'

# 后期打标签
$ git tag -a <tag-name> <version>

# 提交指定 tag
$ git push origin <tag-name>

# 提交所有 tag
$ git push origin --tags

# 删除本地 tag
$ git tag -d <tag-name>

# 删除远程 tag
$ git push origin --detele tag <tag-name>

# 还可以向远程推送一个“空标签”,等同于删除远程标签
$ git push origin :refs/tags/<tag-name>

# 将本地所有不在远程仓库服务器上的标签推送至服务器
git push origin –tags

七、拉取

这里主要有两条命令 git fetchgit pull,区别如下:

  • git fetch:将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到「本地分支」中。
  • git pull:将远程主机的最新内容拉下来后直接合并,相当于:git fetch + git merge FETCH_HEAD

git fetch origin branch-name 虽说会将远程的更新拉取到本地,它会更新至本地的 origin/branch-name 的分支下,换句话说:此时 origin/branch-name 与远程的 branch-name 分支是一致的,都是最新的(请注意,本地的 origin/branch-namebranch-name 是两个独立的分支)。

如果你 Fetch 完成之后,不进行 Merge 或 Rebase 等合并操作,它是不会更新 branch-name 分支内容的。在合并之前,可以利用 git diff branch-name origin/branch-name 去对比两个分支的内容,最终决定是否要将远程的更新合并至本地的 branch-name 分支中。

7.1 git fetch

# 将 git remote 中所有关联的远程仓库包含的所有分支的更新拉取到本地
$ git fetch

# 将远程所有分支的更新拉取至本地
$ git fetch <远程主机名>

# 将远程特定分支的更新拉取至本地
$ git fetch <远程主机名> <分支名>
# git fetch origin main

当拉取成功后,会返回一个 FETCH_HEAD,指的是某个分支在服务器上的最新状态。通过以下方式可以查看刚拉取回来的更新信息:

$ git log -p FETCH_HEAD

我们来试一下,如下图:

图中可以看到一些文件更新信息,包括文件名、更新作者、更新时间、更新代码等,并通过这些信息来判断是否产生冲突。

接着,可以通过 git merge 来将这些拉取下来的最新内容合并到当前分支中:

$ git merge FETCH_HEAD

# 或者使用以下这个,其中 <branch-name> 表示要合并的分支名称,例如 origin/main
$ git merge origin/<branch-name>

7.2 git pull

# 拉取远程某分支的更新,并与本地指定分支合并
$ git pull <远程主机名> <远程分支名>:<本地分支名>
# git pull origin

# 如果远程分支与当前本地分支进行合并,则冒号及后面部分可以省略
$ git pull <远程主机名> <远程分支名>
# git pull origin <branch-name>

因此

$ git pull origin main

# 相当于
$ git fetch origin main
$ git merge FETCH_HEAD

7.3 (建议)少用 Push,多用 Fetch 和 Merge

将拉取和合并独立开来是一个较好的方法,即少用 Push,多用 Fetch 和 Merge。

git pull 的问题是它把过程的细节都隐藏了起来,以至于你不用去了解 Git 中各种类型分支的区别和使用方法。当然,多数时候这是没问题的,但一旦代码有问题,你很难找到出错的地方。看起来 git pull 的用法会使你吃惊,简单看一下 Git 的使用文档应该就能说服你。

将下载(Fetch)和合并(Merge)放到一个命令里的另外一个弊端是,你的本地工作目录在未经确认的情况下就会被远程分支更新。当然,除非你关闭所有的安全选项,否则 git pull 在你本地工作目录还不至于造成不可挽回的损失,但很多时候我们宁愿做的慢一些,也不愿意返工重来。

尤其在多人协作的时候,可能是一个复杂的合并操作,我们可以这样(以 main 分支为例):

# 1. 拉取
$ git fetch origin main

# 2. 比较
$ git diff main origin/main

# 3. 合并
$ git merge origin/main

况且,有些团队的合并操作要求使用 git rebase,而不是 git merge。当然了也有 git pull --rebase 可使用啦。

可参考文章:

八、文件操作

我们知道 .gitignore 仅对未跟踪过的文件才起作用。对于已存在于版本管理库中的文件/目录,我们需要使用 git rm 命令来取消对文件/目录的跟踪。

# 不删除本地文件
$ git rm -r --cached <file-or-dir>

# 删除本地文件
$ git rm -r -f <file-or-dir>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

谜兔

暂无简介

0 文章
0 评论
24 人气
更多

推荐作者

qq_eQNo9e

文章 0 评论 0

内心旳酸楚

文章 0 评论 0

mb_BlPo2I8v

文章 0 评论 0

alipaysp_ZRaVhH1Dn

文章 0 评论 0

alipaysp_VP2a8Q4rgx

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文