使用 Git 管理项目文件和代码

Isabelle收藏家Lv.20归还仪式见证者👁 34♥ 0💬 0

Git 安装和配置

Git 是一个免费、开源的分布式版本控制系统,用于跟踪文件和代码的修改历史,支持多人协作开发。

Git 由 Linus Torvalds 于 2005 年创建,最初用于管理 Linux 内核的代码。与 SVN 等集中式版本控制系统不同,Git 是分布式的,每个克隆出来的仓库都包含完整的项目历史,提交、查看历史、切换分支等大部分操作都能在本地完成。

使用 Git 的必要性

开发过程中,文件会被反复修改。使用 Git 可以:

  • 保存完整历史:每次修改都有记录,可随时对比、回退。
  • 支持多人协作:自动合并各自的改动,冲突时给出提示。
  • 并行开发:新功能、缺陷修复、实验都可以放在独立分支上进行。
  • 数据安全:每个克隆出来的仓库都是完整副本,可随时恢复整个项目。
  • 对接主流平台:GitHub、GitLab、Gitee 等平台和各类 CI/CD 工具都以 Git 为基础。
  • 个人项目:独自开发也能借助版本回退、差异对比管理项目,不必再靠复制多份文件区分版本。

使用 AI 更需要 Git

借助 AI 编写和修改代码时,工具会直接读写项目文件,一次改动可能跨越几十个文件,出错的影响也更大。版本管理的作用更明显:

  • 审查 AI 的改动:用 git diff 查看 AI 修改了什么,确认后再提交。
  • 改错了随时回退:只要之前提交过,就能回退到改动前的版本。
  • 尝试不同方案:让 AI 在多个分支上各写一版,留优弃劣,不影响主线代码。
  • 让 AI 更容易理解项目:清晰规范的提交记录,能让 AI 给出更贴合上下文的建议。
  • 记录 AI 协作情况:在提交信息中标注哪些改动由 AI 生成、哪些经过人工审核。

安装 Git(Windows)

在 Git 官网下载 Windows 安装包,双击安装即可:https://git-scm.com/download/win(项目全称 Git for Windows,也叫做 msysGit)。

其他安装方式:

  • 自动安装:使用社区维护的 Git Chocolatey 包。
  • GitHub Desktop:自带图形化和命令行版本的 Git,也支持 PowerShell。

运行 Git 前的配置

安装后需要配置一次,每台计算机只需一次软件升级时会保留,可以随时再次运行命令修改配置。Git 的配置变量存储在三个位置:

  • --system:/etc/gitconfig,系统全局配置,需要管理员权限才能修改。
  • --global:~/.gitconfig,对当前用户的所有仓库生效。
  • --local:.git/config,默认当前仓库的配置文件。

每一级会覆盖上一级的配置。在 Windows 上,用户级配置位于 C:\Users\<用户名>\.gitconfig,系统级配置在 Git 的安装目录下。

用户信息

第一次使用前必须设置用户名和邮箱,每次提交都需要一起提交:

$ git config --global user.name "名字"
$ git config --global user.email "邮箱"

--global 只要运行一次;如果想针对单个项目使用不同信息时,在项目目录下运行不带 --global 的同样命令。

查看配置

$ git config --list     # 列出所有配置
$ git config user.name  # 查看某一项配置

获取 Git 仓库

有两种方式:把本地目录初始化为仓库、克隆一个已有的仓库。

初始化本地仓库

进入项目目录后执行:

$ git init

这个命令创建一个 .git 子目录,包含仓库所需的全部文件。如果目录中已有文件,继续把它们纳入跟踪并提交:

$ git add *.c
$ git add LICENSE
$ git commit -m 'initial project version'

克隆现有仓库

$ git clone https://github.com/libgit2/libgit2

会在当前目录下创建同名目录并拉取全部历史数据。如果需要自定义目录名,在命令末尾加上新目录名:

$ git clone https://github.com/libgit2/libgit2 mylibgit

记录每次更新到仓库

工作目录下的文件分为两种状态:已跟踪(Git 可以管理)和未跟踪( Git 不能管理)。修改文件后,通过暂存提交保存到仓库。

查看文件状态

$ git status

输出内容很多,可以加 -s 使用紧凑格式:

$ git status -s
 M README
MM Rakefile
A  lib/git.rb
?? LICENSE.txt

左栏是暂存区状态,右栏是工作区状态;?? 表示未跟踪,A 表示新增,M 表示修改。

暂存文件

用 git add 开始跟踪新文件,或把改动放入暂存区:

$ git add README
$ git add CONTRIBUTING.md

git add 暂存的是执行命令时的那个版本;如果之后又改了文件,需要重新 git add 一次。

提交更新

$ git commit              # 打开编辑器输入提交说明
$ git commit -m "说明文字"  # 直接在命令中给出提交说明

提交前先用 git status 确认所需文件都已暂存。提交记录的是暂存区的快照。

跳过暂存直接提交

git commit 加上 -a 选项,会自动暂存所有已跟踪文件的修改并提交,跳过 git add:

$ git commit -a -m 'added new benchmarks'

查看改动

  • git diff:查看尚未暂存的改动。
  • git diff --staged:查看已暂存的改动(与 git diff --cached 同义)。
$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your patch is
+longer than a dozen lines.

+ 开头是新增内容,- 开头是删除内容。

忽略文件

不加入 Git 管理的文件,可以在项目根目录创建 .gitignore 文件排除:

# 忽略所有 .a 文件
*.a

# 但跟踪 lib.a
!lib.a

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

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

# 忽略 doc/ 及其子目录下的所有 .pdf 文件
doc/**/*.pdf
  • 空行和 # 开头的行会被忽略。
  • 支持标准 glob 模式:* 匹配任意字符,? 匹配单个字符,[abc] 匹配方括号中的任一字符,** 匹配任意中间目录。
  • 以(/)开头防止递归;以(/)结尾只匹配目录;模式前加叹号(!)取反。

删除与重命名文件

$ git rm PROJECTS.md            # 删除文件,并停止跟踪
$ git rm --cached README        # 只停止跟踪,保留本地文件
$ git mv README.md README       # 重命名文件

git mv 相当于 mv + git rm + git add 三条命令的组合。

查看提交历史

git log 按时间顺序列出所有提交,最近的排在最上面:

$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

常用查看方式:

$ git log --oneline                              # 每个提交压缩成一行
$ git log -p -2                                  # 显示最近两次提交的具体改动
$ git log --stat                                 # 显示每次提交的文件修改统计
$ git log --pretty=format:"%h - %an, %ar : %s"   # 自定义输出格式
$ git log --since=2.weeks                        # 最近两周的提交
$ git log --author="Scott" --grep="fix"          # 按作者 / 关键字筛选
$ git log -- README.md                           # 只看某个文件的历史

Table1. git log 的常用选项

选项说明
-p按补丁格式显示每个提交的差异。
--stat显示每次提交的文件修改统计。
--oneline每个提交压缩为一行显示。
--graph以 ASCII 图形显示分支与合并历史。
--pretty使用 oneline、short、full、format 等格式显示。

Table2. 限制 git log 输出的选项

选项说明
-<n>仅显示最近的 n 条提交。
--since, --after仅显示指定时间之后的提交。
--until, --before仅显示指定时间之前的提交。
--author仅显示指定作者的提交。
--grep仅显示提交说明中包含指定字符串的提交。
-S仅显示添加或删除内容匹配指定字符串的提交。

撤消操作

修补最后一次提交

漏加了文件,或者提交说明写错了:

$ git add forgotten_file
$ git commit --amend

用新的提交替换上一次提交,仓库历史中不会留下两次记录。

取消暂存的文件

$ git reset HEAD CONTRIBUTING.md

文件会回到“已修改但未暂存”状态。

撤消对文件的修改

$ git checkout -- CONTRIBUTING.md

把文件还原成上次提交时的样子。

git checkout -- <file> 会丢弃该文件在本地的所有修改,无法恢复,确认后再执行。

分支操作

分支可以在独立的工作线上开发新功能,不影响主分支,完成后再合并回去。

创建与切换分支

首先,假设你正在项目上工作,master 分支上已经有一些提交。要处理问题追踪系统中的 #53 问题,先新建一个分支并切换过去:

$ git checkout -b iss53   # 新建分支并立即切换(相当于下面两条命令)
$ git branch iss53        # 只新建分支
$ git checkout iss53      # 只切换到已有分支

之后在 iss53 分支上继续开发并提交。切换分支时,如果工作目录里有未提交的修改,可能会被拒绝切换。

合并分支(快进)

假设此时接到一个紧急修复任务,先切回 master,新建 hotfix 分支处理问题,再合并回 master:

$ git checkout master
$ git checkout -b hotfix
$ vim index.html
$ git commit -a -m 'fixed the broken email address'

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

hotfix 直接延续自 master,Git 只需把指针向前移动,这种情况叫快进(fast-forward)。合并完成后可以删除 hotfix:

$ git branch -d hotfix

合并分支(三方合并)

如果两个分支各自都有新提交(从更早的提交分叉开来),合并时 Git 会做一次三方合并,并自动创建一个合并提交:

$ git checkout master
$ git merge iss53
Merge made by the 'recursive' strategy.
 index.html | 1 +
 1 file changed, 1 insertion(+)

合并完成后,不再需要的分支可以删除:git branch -d iss53。

解决合并冲突

如果两个分支修改了同一文件的同一部分,Git 就无法自动合并,会给出冲突提示:

$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

用 git status 查看处于“未合并”状态的文件:

$ git status
On branch master
You have unmerged paths.

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    both modified:      index.html

打开冲突文件,会看到类似下面的标记:

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
 please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

======= 上面是当前分支(HEAD)的内容,下面是 iss53 分支的内容。保留想要的部分(或自行整合),并删掉 <<<<<<<、=======、>>>>>>> 这些标记行。

解决完所有冲突后,用 git add 把文件标记为已解决(可以用 git status 确认),然后运行 git commit 完成合并提交。也可以使用图形化工具解决冲突:git mergetool。

分支管理

$ git branch               # 列出所有分支,* 表示当前所在分支
$ git branch -v            # 同时显示每个分支的最后一次提交
$ git branch --merged      # 列出已合并到当前分支的分支
$ git branch --no-merged   # 列出尚未合并到当前分支的分支

尚未合并的分支用 -d 删除会失败,确认不再需要时可以强制删除:

$ git branch -d testing   # 未合并时会报错
$ git branch -D testing   # 强制删除

--merged 和 --no-merged 不加参数时比较的是当前分支;在命令后加上分支名,可以查看其它分支的合并情况,例如 git branch --no-merged master。

评论(0)

登录后就能留言,和大家一起聊聊这张卡。

去登录
还没有人评论,来抢第一条沙发吧。