git 一个分布式版本控制系统,由Linus Torvalds(芬兰计算机科学家,linux之父呀)在2005创建,最初是为了帮助管理 Linux 内核的开发而设计

使用git可以协作并行工作,版本控制,可以创建分支轻松合并更改,代码保存在多个地方,防止数据丢失。

Git的核心概念

  • 仓库 (Repository): 你的项目代码库,包含所有文件和历史记录。

    • 本地仓库: 在你电脑上的仓库。
    • 远程仓库: 在线托管的仓库,例如GitHub、GitLab、Gitee。
  • 工作区 (Working Directory): 你在电脑上看到和编辑的实际文件。

  • 暂存区 (Staging Area / Index): 一个临时区域,用于存放你准备提交(commit)的更改。你可以选择性地将文件添加到暂存区。

  • 提交 (Commit): 将暂存区的更改永久保存到本地仓库中,并生成一个唯一的**提交ID (Commit ID)**。每次提交都像是一个项目状态的“快照”。

  • 分支 (Branch): 从主线(通常是mainmaster分支)分出来的独立开发路径。你可以在不影响主线代码的情况下进行新功能开发或修复bug。

  • 合并 (Merge): 将一个分支的更改合并到另一个分支。

  • 拉取 (Pull): 从远程仓库下载最新的更改到本地仓库,并自动合并。

  • 推送 (Push): 将本地仓库的更改上传到远程仓库。

Git安装与配置

从git官方下载适合的安装,安装完后验证安装:

1
git --version
  • 配置Git

安装完成后,需要配置你的用户名和邮箱,在每次提交时显示,这对于团队协作和追溯历史非常重要。

1
2
git config --global user.name "你的用户名"
git config --global user.email "你的邮箱@example.com"
  • --global 参数表示这些配置是全局的,对电脑上所有的Git仓库都有效。如果想为某个特定仓库设置不同的用户名和邮箱,可以进入该仓库目录后不加 --global 参数进行配置。
  • 检查配置

可使用以下命令检查配置:

1
2
3
4
5
git config --list

# 查看特定配置
git config user.name
git config user.email

Git核心工作流程:工作区、暂存区、本地仓库

核心工作流程图示:

1
2
3
4
5
6
7
8
9
10
11
+----------------+       +-------------------+       +-------------------+
| 工作区 | ----> | 暂存区 | ----> | 本地仓库 |
| (Working Dir) | | (Staging Area) | | (Local Repo) |
| | | | | |
| 你编辑文件 | | 准备下次提交的 | | 已提交的历史 |
| 创建/修改/删除 | | 文件快照清单 | | 所有版本记录 |
+----------------+ +-------------------+ +-------------------+
^ | ^
| | |
| 修改文件 | git add | git commit
+------------------------+-------------------------+

实际操作流程:

  1. 你在工作区修改文件。
  2. 使用 git add <文件名>git add . 将你希望跟踪的更改从工作区添加到暂存区
  3. 使用 git commit -m "提交信息"暂存区的所有内容提交到本地仓库,形成一个新的版本。

Git基本操作

现在我们开始实践Git的基本操作。

1. 初始化一个新的Git仓库

如果有一个全新的项目,要被Git管理,需要初始化一个Git仓库。

1
2
# 进入项目根目录
cd /path/to/

然后执行:

1
git init

这会在你的项目目录下创建一个名为 .git 的隐藏文件夹,这就是你的Git仓库,它包含了Git所需的所有信息。

2. 添加文件到暂存区

对文件进行更改后,需要告诉Git希望跟踪这些更改。

1
2
git add <文件名> # 添加单个文件
git add . # 添加当前目录下的所有更改(包括新建、修改、删除)

3. 提交更改

将暂存区的更改提交到本地仓库。每次提交都应该有一个清晰的**提交信息 (Commit Message)**,描述你这次提交做了什么。

1
git commit -m "你的提交信息"

一个好的提交信息能够帮助你和团队成员快速理解每次更改的目的。例如:

1
git commit -m "feat: 添加部署指南"
  • 小技巧:

    提交信息建议使用动词开头,清晰明了。常见的提交信息前缀:

    • feat: 新功能 (feature)
    • fix: 修复bug (bug fix)
    • docs: 文档变更 (documentation)
    • style: 代码格式化 (whitespace, formatting)
    • refactor: 代码重构 (refactoring)
    • test: 增加测试 (tests)
    • chore: 构建过程或辅助工具的变动 (build process, auxiliary tools)

4. 查看仓库状态

git status 命令非常常用,它会显示你工作区和暂存区的状态,以及哪些文件被修改、哪些文件是未跟踪的。

1
git status
  • 红色文件名: 未跟踪的文件(untracked files)或已修改但未添加到暂存区的文件。
  • 绿色文件名: 已添加到暂存区的文件。

5. 查看提交历史

git log 命令可以查看提交历史,包括提交ID、作者、日期和提交信息。

1
git log

你也可以使用一些参数让输出更简洁:

1
2
3
4
5
6
git log --oneline # 每条提交显示一行
git log --graph --oneline --decorate # 以图形方式显示分支和提交
git log -p # 显示每次提交的详细内容差异 (patch)。
git log --author="你的名字" # 只显示特定作者的提交。
git log --since="2 weeks ago" # 显示最近两周的提交。
git log <文件名> # 只显示某个文件的修改历史。

通过状态与历史:git statusgit log可随时了解仓库的健康状况和发展历程。

当有多条分支和合并操作时 --graph会非常直观…

6. 忽略文件:.gitignore

项目中,有些文件或目录不想被git跟踪,比如:临时文件,敏感信息,依赖包等,如果不忽略导致仓库臃肿且不必要。

在项目根目录下创建一个名为 .gitignore 的文件(注意文件名以点开头),然后将.gitignore文件本身添加到git并提交。

1
2
git add .gitignore
git commit -m "Add .gitignore file"

6.1 .gitignore 语法

每行定义一个忽略规则。

  • 空行 或以 # 开头的行都会被忽略。
  • *****:匹配零个或多个字符。
  • **?**:匹配单个字符。
  • **[]**:匹配括号内的任何一个字符(例如 [abc] 匹配 ‘a’, ‘b’, 或 ‘c’)。
  • ****:匹配任意目录层级。
  • / 结尾: 表示忽略目录,不包含其下的子文件。
  • ! 开头: 表示不忽略某个文件或目录(即使它被前面的规则忽略了)。

注意: 如果已经不小心把某个应该忽略的文件提交到了仓库,然后才添加到 .gitignore,Git不会自动从历史中删除它。需要手动从Git的跟踪中移除它:

1
2
git rm --cached <文件名>
git commit -m "Remove <文件名> from tracking"

--cached 参数表示只从Git的暂存区和仓库中移除,但保留你工作区的实际文件。

分支管理——Git的灵魂

分支 (Branch) 就像是 Git 提供的一条独立的开发路径。它允许你在不影响主线开发(通常是 mainmaster 分支)的情况下,进行新功能的开发、bug 修复或实验性尝试。

在 Git 中,分支的本质只是一个指向某次提交 (commit) 的指针。 默认情况下,Git 会创建一个名为 main (或 master) 的主分支。当你进行提交时,这个分支指针就会向前移动。

1. git基本工作流:

  • 克隆(Clone): 从远程仓库复制项目到本地,创建一个本地仓库的副本。

  • 添加(Add): 将修改后的文件添加到暂存区,准备提交。

  • 提交(Commit): 将暂存区的更改永久保存到本地仓库,并附上一条描述性的提交信息。

  • 推送(Push): 将本地仓库的提交推送到远程仓库,更新远程仓库的内容。

  • 拉取(Pull): 从远程仓库获取最新的更改,与本地仓库同步。

  • 分支管理(Branching): 创建、切换、合并和删除分支,以支持并行开发和功能独立性。

2. Git 的命令行操作

以下是一些常用的 Git 命令:

  • git clone <remote_repository_url>:克隆远程仓库到本地。
  • git add <file_path>:将指定文件添加到暂存区。
  • git commit -m "commit_message":提交暂存区的更改到本地仓库。
  • git push origin <branch_name>:将本地仓库的提交推送到远程仓库。
  • git pull origin <branch_name>:从远程仓库拉取最新更改到本地。
  • git branch:查看当前所有分支。
  • git checkout <branch_name>:切换到指定分支。
  • git merge <branch_name>:合并指定分支到当前分支。

3. 示例流程

1
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
32
➜  ~ mkdir beizi_blog
➜ ~ cd beizi_blog/
➜ ~/beizi_blog git init
已初始化空的 Git 仓库于 /Users/bz/beizi_blog/.git/
# 这会在当前目录下创建一个隐藏的 .git 文件夹,用来存储 Git 的版本控制相关信息。

➜ ~/beizi_blog git remote -v
beizi_blog git@github.com:beiziya/beizi_blog.git (fetch)
beizi_blog git@github.com:beiziya/beizi_blog.git (push)
origin git@github.com:beiziya/beizi_blog.git (fetch)
origin git@github.com:beiziya/beizi_blog.git (push)
# 之前已经添加过远程仓库,又添加了一个

➜ ~/beizi_blog touch test.txt
➜ ~/beizi_blog echo "this is a test" >test.txt
➜ ~/beizi_blog cat test.txt
this is a test
➜ ~/beizi_blog git add . # 添加当前目录所有文件到暂存区

➜ ~/beizi_blog git commit -m "first file"
[main(根提交) c4b8e0c] first file
1 file changed, 1 insertion(+)
create mode 100644 test.txt
➜ ~/beizi_blog git push -u beizi_blog main # 推送到远程仓库
枚举对象中: 3, 完成.
对象计数中: 100% (3/3), 完成.
写入对象中: 100% (3/3), 218 字节 | 218.00 KiB/s, 完成.
总共 3(差异 0),复用 0(差异 0),包复用 0(来自 0 个包)
To github.com:beiziya/beizi_blog.git
* [new branch] main -> main
分支 'main' 设置为跟踪 'beizi_blog/main'

-u 参数只需在第一次推送分支时使用。之后,可以直接使用 git push

如果已经设置过关联,也可以手动设置本地分支与远程分支的关联,例如:

1
git branch --set-upstream-to=origin/main main

前提:远程有beizi_blog仓库,并设置好ssh key或 gpg key 我已经设置好了。以下设置步骤

设置ssh key

1
2
3
4
5
6
7
8
9
➜  ~/beizi_blog ls ~/.ssh
beiziya_id_rsa config id_rsa.pub known_hosts.old
beiziya_id_rsa.pub id_rsa known_hosts
# 可以看到有我的公私钥,可通过ssh-keygen生成
# -t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa
# Specifies the type of key to create. The possible values are
# “dsa”, “ecdsa”, “ecdsa-sk”, “ed25519”, “ed25519-sk”, or “rsa”.
#可以指定不同加密算法

1
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
32
33
34
35
➜  ~/beizi_blog ssh-keygen -t rsa -b 4096 -C "test keys" #测试生成密钥对到当前目录
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/bz/.ssh/id_rsa): beizi_blog_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in beizi_blog_rsa
Your public key has been saved in beizi_blog_rsa.pub
The key fingerprint is:
SHA256:yWreqJG5jxl6c+cRcfiP9zMyP1s0haTP6htro26YyP4 test keys
The key's randomart image is:
+---[RSA 4096]----+
| . |
| . o . |
| o . . . .|
| . = o .|
| S . o..|
| o . . o . ..|
| =.o..o. = .|
| .oO+o+..o=++. |
| ..=*=+Eooo+*+= |
+----[SHA256]-----+
➜ ~/beizi_blog ls
beizi_blog_rsa beizi_blog_rsa.pub test.txt

# 注:千万不能把密钥放到项目目录中,这只是测试


# 将ssh key添加到ssh代理
eval "$(ssh-agent -s)"
ssh-add ./beizi_blog_rsa

# 将.pub中的内容复制到剪贴板
pbcopy < ./beizi_blog_rsa.pub # macos

#粘贴到git帐户ssh keys中

如果想让不同的密钥对访问不同主机,需要建立ssh config 文件

1
2
3
4
5
6
7
8
9
10
11
12
# GitHub
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github_rsa

# GitLab
Host gitlab.com
HostName gitlab.com
User your_username
IdentityFile ~/.ssh/gitlab_rsa