1.GitHub入门与实践
参考资料:《GitHub入门与实践》
声明:本篇博客内容由笔者跟随该书进行实际操作并记录过程而来,该篇博客内容大部分来自上述提到的书中。
GitHub入门与实践
- 1.GitHub入门与实践
-
- [1.1 对本地计算机里安装的 Git 进行设置](#1.1 对本地计算机里安装的 Git 进行设置)
- [1.2 使用github的前期准备](#1.2 使用github的前期准备)
-
- [1.2.1 创建账户设置基本信息](#1.2.1 创建账户设置基本信息)
- [1.2.2 设置SSH Key](#1.2.2 设置SSH Key)
- [1.2.2 在github帐号内添加公钥](#1.2.2 在github帐号内添加公钥)
- [1.3 创建仓库](#1.3 创建仓库)
- [1.4 公开代码](#1.4 公开代码)
-
- [1.4.1 git clone (将github远程仓库克隆到本地)](#1.4.1 git clone (将github远程仓库克隆到本地))
- [1.4.2 coding (本地编写代码)](#1.4.2 coding (本地编写代码))
- [1.4.3 git status (查看仓库状态)](#1.4.3 git status (查看仓库状态))
- [1.4.4 git add (添加到暂存区) / git commit(保存仓库历史记录) / git log(查看提交日志)](#1.4.4 git add (添加到暂存区) / git commit(保存仓库历史记录) / git log(查看提交日志))
- [1.4.5 git push (代码推送回github远程仓库)](#1.4.5 git push (代码推送回github远程仓库))
- [1.5 基本操作](#1.5 基本操作)
-
- [1.5.1 git init (初始化仓库)](#1.5.1 git init (初始化仓库))
- [1.5.2 git status(查看仓库的状态)](#1.5.2 git status(查看仓库的状态))
- [1.5.3 git add(向暂存区中添加文件)](#1.5.3 git add(向暂存区中添加文件))
- [1.5.4 git commit(保存仓库的历史记录)](#1.5.4 git commit(保存仓库的历史记录))
- [1.5.5 git log(查看提交日志)](#1.5.5 git log(查看提交日志))
- [1.5.6 git diff(查看更改前后的差别)](#1.5.6 git diff(查看更改前后的差别))
- [1.6 分支操作](#1.6 分支操作)
-
- [1.6.1 git branch(显示分支一览表)](#1.6.1 git branch(显示分支一览表))
- [1.6.2 git checkout -b(创建、切换分支)](#1.6.2 git checkout -b(创建、切换分支))
- [1.6.3 git merge(合并分支)](#1.6.3 git merge(合并分支))
- [1.6.4 git log --graph(以图表形式查看分支)](#1.6.4 git log --graph(以图表形式查看分支))
- [1.7 更改提交的操作](#1.7 更改提交的操作)
-
- [1.7.1 git reset(回溯历史版本)](#1.7.1 git reset(回溯历史版本))
- [1.7.2 git commit --amend(修改提交信息)](#1.7.2 git commit --amend(修改提交信息))
- [1.7.3 git rebase -i(压缩历史)](#1.7.3 git rebase -i(压缩历史))
- [1.8 推送至远程仓库](#1.8 推送至远程仓库)
-
- [1.8.1 git remote add(添加远程仓库)](#1.8.1 git remote add(添加远程仓库))
- [1.8.2 git push(推送至远程仓库)](#1.8.2 git push(推送至远程仓库))
- [1.9 从远程仓库获取](#1.9 从远程仓库获取)
-
- [1.9.1 git clone(获取远程仓库)](#1.9.1 git clone(获取远程仓库))
- [1.9.2 git pull (获取最新的远程仓库分支)](#1.9.2 git pull (获取最新的远程仓库分支))
- [1.10 尝试Pull Request](#1.10 尝试Pull Request)
- [1.11 接收Pull Request](#1.11 接收Pull Request)
下图改编自in/viciloria
1.1 对本地计算机里安装的 Git 进行设置
首先来设置使用 Git 时的姓名和邮箱地址
bash
$ git config --global user.name "Firstname Lastname"
$ git config --global user.email "your_email@example.com"
1.2 使用github的前期准备
1.2.1 创建账户设置基本信息
1.2.2 设置SSH Key
GitHub 上连接已有仓库时的认证,是通过使用了 SSH 的公开密钥认证方式进行的。现在让我们来创建公开密钥认证所需的 SSH Key,并将其添加至 GitHub
运行下面的命令创建 SSH Key
bash
$ ssh-keygen -t rsa -C "your_email@example.com"
Generating public/private rsa key pair.
Enter file in which to save the key
(/Users/your_user_directory/.ssh/id_rsa): 按回车键
Enter passphrase (empty for no passphrase): 输入密码
Enter same passphrase again: 再次输入密码
输入密码后会出现以下结果
bash
Your identification has been saved in /Users/your_user_directory/.ssh/id_rsa.
Your public key has been saved in /Users/your_user_directory/.ssh/id_rsa.pub.
The key fingerprint is:
fingerprint值 your_email@example.com
The key's randomart image is:
+--[ RSA 2048]----+
|.++|
|= o O .|
id_rsa 文件是私有密钥,id_rsa.pub 是公开密钥
在 GitHub 中添加公开密钥,今后使用私钥进行认证
1.2.2 在github帐号内添加公钥
Title自己取名字,Key type用默认,Key添加之前生成的公钥
使用以下命令查看公钥,并将该公钥添加到上图中Key的位置
bash
$ cat ~/.ssh/id_rsa.pub
ssh-rsa 公开密钥的内容 your_email@example.com
用手中的私人密钥与 GitHub 进行认证和通信
输入命令
bash
ssh -T git@github.com
Enter passphrase for key '~/.ssh/id_rsa': [输入自己github密码]
Hi,aaa.You've successfully authenticated,but github does not provide shell access.
1.3 创建仓库
右上角创建新仓库
README.md
一般在这个文件中标明本仓库所包含
(1) 软件的概要
(2) 使用流程
(3) 许可协议
等信息
.gitignore文件的作用
.gitignore 文件通过指定忽略规则,帮助开发者管理项目中不必要提交的文件,优化项目的存储和协作效率,同时防止敏感信息的意外泄露。
常见许可协议
1.4 公开代码
尝试在已有仓库中添加代码并加以公开
刚刚创建的仓库的页面
1.4.1 git clone (将github远程仓库克隆到本地)
首先将已有仓库 clone 到本地的开发环境中
bash
$ git clone git@github.com:irvingwu5/hello_world.git
Cloning into 'hello_world'...
Enter passphrase for key '/home/.../.ssh/id_rsa': [输入github密码]
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (3/3), done.
bash
cd hello_world/
ls
README.md
1.4.2 coding (本地编写代码)
这里我们编写一个 hello.cpp 文件
1.4.3 git status (查看仓库状态)
由于 hello.cpp 还没有添加至 Git 仓库,所以显示为 Untracked files
bash
$ git status
On branch main
Your branch is up to date with 'origin/main'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello.cpp
nothing added to commit but untracked files present (use "git add" to track)
1.4.4 git add (添加到暂存区) / git commit(保存仓库历史记录) / git log(查看提交日志)
通过 git add命令将文件加入暂存区 A,再通过 git commit命令提交。添加成功后,可以通过 git log命令查看提交日志
将 hello.cpp 提交 (commit) 至仓库。这样一来,这个文件就进入了版本管理系统的管理之下。今后的更改管理都交由 Git 进行
bash
$ git add hello.cpp
$ git commit -m "Add hello script by cpp"
[main 5f4b9e4] Add hello script by cpp
1 file changed, 28 insertions(+)
create mode 100644 hello.cpp
$ git log
commit ........ (HEAD -> main)
Author: Wu Irving <....@....com>
Date: Fri Oct 4 16:35:20 2024 +0800
Add hello script by cpp
commit ........ (origin/main, origin/HEAD)
Author: Wu Xiang Yu <124986252+irvingwu5@users.noreply.github.com>
Date: Fri Oct 4 16:12:46 2024 +0800
Initial commit
1.4.5 git push (代码推送回github远程仓库)
bash
$ git push
Enter passphrase for key '/home/.../.ssh/id_rsa': [输入github密码]
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 16 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 718 bytes | 718.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:irvingwu5/hello_world.git
f68e6e2..5f4b9e4 main -> main
1.5 基本操作
1.5.1 git init (初始化仓库)
要使用 Git 进行版本管理,必须先初始化仓库。Git 是使用 git init命令进行初始化的。请实际建立一个目录并初始化仓库
本地终端输入命令,创建空目录,进入目录,进行初始化操作
bash
$ mkdir git-tutorial
$ cd git-tutorial/
$ git init
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /home/.../Documents/CppProjects/git-tutorial/.git/
git init 是一个 Git 命令,用于初始化一个新的 Git 仓库。它的作用主要包括:
1.创建版本控制环境:git init 命令会在当前目录下创建一个新的 .git 子目录,这个子目录包含了 Git 版本控制所需的所有文件和结构。
2.开始跟踪文件:通过执行 git init,你可以开始将当前目录中的文件纳入版本控制。这意味着你可以使用其他 Git 命令(如 git add 和 git commit)来跟踪和管理文件的更改。
3.准备项目进行协作:如果你计划将这个项目与他人共享或将其推送到远程仓库(如 GitHub),那么 git init 是第一步。
在 Git 中,我们将这个目录(.git)的内容称为"附属于该仓库的工作树"。
文件的编辑等操作在工作树中进行,然后记录到仓库中,以此管理文件的历史快照。
如果想将文件恢复到原先的状态,可以从仓库中调取之前的快照,在工作树中打开。开发者可以通过这种方式获取以往的文件。
.git下各个目录和文件的含义
1.5.2 git status(查看仓库的状态)
工作树和仓库在被操作的过程中,状态会不断发生变化。在 Git 操作过程中时常用 git status命令查看当前状态
工作树与 .git 目录的关系
工作树:你直接操作和编辑的文件。这些文件可以是源代码、文档、图像等,属于项目的实际内容。
.git 目录:用于存储与版本控制相关的元数据和对象。它管理版本历史、索引、配置和其他版本控制信息。
工作树示意图:
bash
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
on branch master表明我们当前正处在master分支下
提交(Commit),是指"记录工作树中所有文件的当前状态"。"No commits yet" 尚没有可提交的内容,就是说当前我们建立的这个仓库中还没有记录任何文件的任何状态。
这里,我们建立 README.md 文件作为管理对象,为第一次提交做前期准备
bash
$ touch README.md
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
nothing added to commit but untracked files present (use "git add" to track)
1.5.3 git add(向暂存区中添加文件)
如果只是用 Git 仓库的工作树创建了文件 (touch README.md),那么该文件并不会被记入 Git 仓库的版本管理对象当中。因此我们用 git status命令查看README.md 文件时,它会显示在 Untracked files 里
要想让文件成为 Git 仓库的管理对象,就需要用 git add命令将其加入暂存区(Stage 或者 Index)中。暂存区是提交之前的一个临时区域
bash
$ git add README.md
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.md
将 README.md 文件加入暂存区后,git status命令的显示结果发生了变化。 可以看到,README.md 文件显示在 Changes to be committed 中了
1.5.4 git commit(保存仓库的历史记录)
git commit命令可以将当前暂存区中的文件实际保存到仓库的历史记录中。通过这些记录,我们就可以在工作树中复原文件。
记述一行提交信息
bash
$ git commit -m "First Commit" #加-m参数,则输入一行提交信息
[master (root-commit) db370d2] First Commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README.md
提交信息示意图:(当仓库被push到github上才能在页面看到)
记述详细提交信息
bash
$ touch hello.cpp
$ git add hello.cpp
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: hello.cpp
$ git commit #不加-m参数,则输入详细提交信息
# Please enter the commit message for your changes. Lines starting (第一行)
# with '#' will be ignored, and an empty message aborts the commit.
#(空行)
# On branch master(第三行以后)
# Changes to be committed: (可以查看本次提交中包含的文件)
# new file: hello.cpp
no add anything
第一行:用一行文字简述提交的更改内容
第二行:空行
第三行以后:记述更改的原因和详细内容
查看当前状态
bash
$ git status
On branch master
nothing to commit, working tree clean
当前工作树处于刚刚完成提交的最新状态,所以结果显示没有更改
1.5.5 git log(查看提交日志)
git log命令可以查看以往仓库中提交的日志。包括可以查看什么人在什么时候进行了提交或合并,以及操作前后有怎样的差别。
来看看刚才的 git commit命令是否被记录了
bash
$ git log
commit 1cbd40573990df40f6e7f55bcc58a5c182917d67 (HEAD -> master)
Author: Wu Irving <...@....com>
Date: Fri Oct 4 18:14:40 2024 +0800
no add anything
commit db370d29535422a4a44630ee0a8af9f52ee3569b #指向这个提交的哈希值,Git的其他命令中,在指向提交时会用到这个哈希值
Author: Wu Irving <...@.....com>
Date: Fri Oct 4 17:59:57 2024 +0800
First Commit
只显示提交信息的第一行
如果只想让程序显示第一行简述信息,可以在 git log命令后加上 --pretty=short。这样一来开发人员就能够更轻松地把握多个提交
bash
$ git log --pretty=short
commit 1cbd40573990df40f6e7f55bcc58a5c182917d67 (HEAD -> master)
Author: Wu Irving <....@.....com>
no add anything
commit db370d29535422a4a44630ee0a8af9f52ee3569b
Author: Wu Irving <....@.....com>
First Commit
只显示指定目录、文件的日志
只要在 git log命令后加上目录名,便会只显示该目录下的日志
如果加的是文件名,就会只显示与该文件相关的日志
bash
$ git log README.md
commit db370d29535422a4a44630ee0a8af9f52ee3569b
Author: Wu Irving <....@.....com>
Date: Fri Oct 4 17:59:57 2024 +0800
First Commit
显示文件的改动
如果想查看提交所带来的改动,可以加上 - p参数,文件的前后差别就会显示在提交信息之后
bash
$ git log -p
commit 1cbd40573990df40f6e7f55bcc58a5c182917d67 (HEAD -> master)
Author: Wu Irving <....@.....com>
Date: Fri Oct 4 18:14:40 2024 +0800
no add anything
diff --git a/hello.cpp b/hello.cpp
new file mode 100644
index 0000000..e69de29
commit db370d29535422a4a44630ee0a8af9f52ee3569b
Author: Wu Irving <....@.....com>
Date: Fri Oct 4 17:59:57 2024 +0800
First Commit
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
只查看 README.md 文件的提交日志以及提交前后的差别
bash
$ git log -p README.md
commit db370d29535422a4a44630ee0a8af9f52ee3569b
Author: Wu Irving <....@.....com>
Date: Fri Oct 4 17:59:57 2024 +0800
First Commit
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
1.5.6 git diff(查看更改前后的差别)
git diff命令可以查看工作树、暂存区、最新提交之间的差别。
在README.md文件中添加文字,查看更改前后差别
查看工作树和暂存区的差别
bash
$ git diff
diff --git a/README.md b/README.md
index e69de29..6e35e14 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1 @@
+#git tutorial #"+"号标出的是新添加的行,被删除的行则用"-"号标出
由于我们尚未用 git add命令向暂存区添加任何东西,所以程序只会显示工作树与最新提交状态之间的差别
用 git add命令将 README.md 文件加入暂存区
bash
$ git add README.md
如果现在执行 git diff命令,由于工作树和暂存区的状态并无差别,结果什么都不会显示
要查看与最新提交的差别使用命令 git diff HEAD
bash
$ git diff HEAD
diff --git a/README.md b/README.md
index e69de29..6e35e14 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1 @@
+#git tutorial
习惯养成:在执行 git commit命令之前先执行git diff HEAD命令,查看本次提交与上次提交之间有什么差别,等确认完毕后再进行提交。(这里的 HEAD 是指向当前分支中最新一次提交的指针)
使用git commit将刚刚修改过的文件保存到仓库的历史记录中
bash
$ git commit -m "Add function"
[master d16037b] Add function
1 file changed, 1 insertion(+)
查看日志,确认是否提交成功
bash
$ git log
commit d16037ba205b79554d772ce8bed20c7b13731760 (HEAD -> master)
Author: Wu Irving <....@.....com>
Date: Fri Oct 4 18:47:02 2024 +0800
Add function
commit 1cbd40573990df40f6e7f55bcc58a5c182917d67
Author: Wu Irving <....@.....com>
Date: Fri Oct 4 18:14:40 2024 +0800
no add anything
commit db370d29535422a4a44630ee0a8af9f52ee3569b
Author: Wu Irving <....@.....com>
Date: Fri Oct 4 17:59:57 2024 +0800
First Commit
1.6 分支操作
1.6.1 git branch(显示分支一览表)
git branch命令可以将分支名列表显示,同时可以确认当前所在分支
bash
$ git branch
* master #星号表示当前所在分支
1.6.2 git checkout -b(创建、切换分支)
bash
$ git checkout -b feature-A #创建并切换分支
Switched to a new branch 'feature-A'
等价于
bash
$ git branch feature-A #创建分支
$ git checkout feature-A #切换分支
查看分支情况
bash
$ git branch
* feature-A
master
feature-A 分支左侧标有"*",表示当前分支为 feature-A。在这个状态下像正常开发那样修改代码、执行 git add命令并进行提交的话,代码就 会提交至 feature-A 分支。 像这样不断对一个分支(例如feature-A)进行提交的操作,我们称为 "培育分支"
在README.md中添加一行后进行提交
bash
$ nano README.md
#git tutorial
-feature-A
$ git add README.md
$ git commit -m "Add feature-A"
[feature-A bd15091] Add feature-A
1 file changed, 1 insertion(+)
README.md中这一行内容添加到了feature-A分支中了
现在我们再来看一看 master 分支有没有受到影响。首先切换至master 分支,然后查看 README.md 文件,会发现 README.md 文件仍然保持原先的状态,并没有被添加文字。feature-A 分支的更改不会影响到master 分支,这正是在开发中创建分支的优点。只要创建多个分支,可以在不互相影响的情况下同时进行多个功能的开发。
bash
$ git checkout master
Switched to branch 'master'
$ nano README.md
#git tutorial
feature-A分支中README.md内容
bash
#git tutorial
-feature-A
master分支中README.md内容
bash
#git tutorial
切换回上一个分支
用"-"(连字符)代替分支名,就可以切换至上一个分支
bash
$ git checkout -
Switched to branch 'feature-A'
主干分支、特性分支
1.6.3 git merge(合并分支)
假设 feature-A 已经实现完毕,想要将它合并到主干分支 master 中。首先切换到 master 分支
bash
$ git branch
* feature-A
master
$ git checkout master
Switched to branch 'master'
$ git branch
feature-A
* master
合并 feature-A 分支。为了在历史记录中明确记录下本次分支合并,我们需要创建合并提交。因此,在合并时加上 --no-ff参数
bash
$ git merge --no-ff feature-A
# 随后编辑器会启动,用于录入合并提交的信息
Merge branch 'feature-A'
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
# 默认信息中已经包含了是从 feature-A 分支合并过来的相关内容,所以可不必做任何更改。将编辑器中显示的内容保存,关闭编辑器,然后就会看到下面的结果。
Merge made by the 'ort' strategy.
README.md | 1 +
1 file changed, 1 insertion(+)
1.6.4 git log --graph(以图表形式查看分支)
用 git log --graph命令进行查看的话,能很清楚地看到特性分支(feature-A)提交的内容已被合并。除此以外,特性分支的创建以及合并也都清楚明了
bash
$ git log --graph
* commit 1515c54edfd7ddfaba476e67c0b52bf878c3af78 (HEAD -> master)
|\ Merge: d16037b bd15091
| | Author: Wu Irving <....@.....com>
| | Date: Fri Oct 4 19:48:23 2024 +0800
| |
| | Merge branch 'feature-A'
| |
| * commit bd15091d17ef71bf63e98e9e501d4b66ba43fe67 (feature-A)
|/ Author: Wu Irving <....@.....com>
| Date: Fri Oct 4 19:17:40 2024 +0800
|
| Add feature-A
|
* commit d16037ba205b79554d772ce8bed20c7b13731760
| Author: Wu Irving <....@.....com>
| Date: Fri Oct 4 18:47:02 2024 +0800
|
| Add function
|
* commit 1cbd40573990df40f6e7f55bcc58a5c182917d67
| Author: Wu Irving <....@.....com>
| Date: Fri Oct 4 18:14:40 2024 +0800
|
....
....
1.7 更改提交的操作
1.7.1 git reset(回溯历史版本)
回溯历史
要让仓库的 HEAD、暂存区、当前工作树回溯到指定状态,需要用到 git reset --hard命令。只要提供目标时间点的哈希值 A,就可以完全恢复至该时间点的状态
bash
$ git log --graph
* commit 1515c54edfd7ddfaba476e67c0b52bf878c3af78 (HEAD -> master)
|\ Merge: d16037b bd15091
| | Author: Wu Irving <....@.....com>
| | Date: Fri Oct 4 19:48:23 2024 +0800
| |
| | Merge branch 'feature-A'
| |
| * commit bd15091d17ef71bf63e98e9e501d4b66ba43fe67 (feature-A)
|/ Author: Wu Irving <....@.....com>
| Date: Fri Oct 4 19:17:40 2024 +0800
|
| Add feature-A
|
* commit d16037ba205b79554d772ce8bed20c7b13731760
| Author: Wu Irving <....@.....com>
| Date: Fri Oct 4 18:47:02 2024 +0800
|
| Add function
|
* commit 1cbd40573990df40f6e7f55bcc58a5c182917d67
| Author: Wu Irving <....@.....com>
| Date: Fri Oct 4 18:14:40 2024 +0800
|
....
....
回溯到特性分支(feature-A)创建之前的状态
bash
$ git reset --hard 1515c54edfd7ddfaba476e67c0b52bf878c3af78
HEAD is now at bd15091 Add feature-A
bash
$ git log --graph
* commit bd15091d17ef71bf63e98e9e501d4b66ba43fe67 (HEAD -> master)
| Author: Wu Irving <....@.....com>
| Date: Fri Oct 4 19:17:40 2024 +0800
|
| Add feature-A
|
* commit d16037ba205b79554d772ce8bed20c7b13731760
| Author: Wu Irving <....@.....com>
| Date: Fri Oct 4 18:47:02 2024 +0800
|
| Add function
|
* commit 1cbd40573990df40f6e7f55bcc58a5c182917d67
| Author: Wu Irving <....@.....com>
| Date: Fri Oct 4 18:14:40 2024 +0800
|
| no add anything
|
* commit db370d29535422a4a44630ee0a8af9f52ee3569b
Author: Wu Irving <....@.....com>
Date: Fri Oct 4 17:59:57 2024 +0800
First Commit
1.7.2 git commit --amend(修改提交信息)
要修改上一条提交信息,可以使用 git commit --amend命令
bash
$ git commit --amend
1.7.3 git rebase -i(压缩历史)
git rebase -i(交互式 rebase)中的"压缩历史"指的是将多个提交合并为一个或多个提交,从而精简和整理 Git 提交历史。这对于清理开发过程中频繁的小提交、合并重复的提交、或者让项目的提交历史更为清晰整洁非常有用。
假设你有以下的提交历史:
bash
commit 789def4 (HEAD -> feature)
Author: You
Date: Fri Oct 1 2024
Fix typo in README
commit 456abc7
Author: You
Date: Fri Oct 1 2024
Improve README format
commit 123abc1
Author: You
Date: Fri Oct 1 2024
Add initial README
现在,你希望将这些三个提交压缩成一个提交,整理成一个单一的提交来描述你对 README 文件的所有修改。这时可以使用 git rebase -i。
步骤一:运行 git rebase -i 命令,指定需要进行压缩的范围。例如,你想将最后三次提交合并,可以运行:
bash
git rebase -i HEAD~3
步骤二:执行命令后,Git 会打开一个文本编辑器,显示类似如下的界面:
bash
pick 123abc1 Add initial README
pick 456abc7 Improve README format
pick 789def4 Fix typo in README
其中,每个 pick 表示一个提交。默认情况下,Git 会按历史顺序保留这些提交。
步骤三:为了将这些提交压缩为一个,你可以将第二和第三个 pick 修改为 squash 或 s,像这样:
bash
pick 123abc1 Add initial README # pick:保留提交。
squash 456abc7 Improve README format # squash:将该提交的更改压缩(合并)到前一个提交中。
squash 789def4 Fix typo in README
步骤四:保存并退出编辑器后,Git 会合并这些提交,并打开另一个编辑器,让你修改新的提交信息。你可以选择保留各个提交的原始消息,或者编写一个新的提交消息。比如:
bash
Add initial README and improvements
- Add initial README
- Improve README format
- Fix typo in README
步骤五:保存提交消息后,Git 会完成压缩操作。最终,提交历史会变成如下所示:
bash
commit 9abcdef (HEAD -> feature)
Author: You
Date: Fri Oct 1 2024
Add initial README and improvements
经过 git rebase -i 压缩后,原来的三个提交被合并为一个提交,整个历史变得更加简洁,提交信息更具代表性,避免了过于细碎的提交。
1.8 推送至远程仓库
1.8.1 git remote add(添加远程仓库)
在 GitHub 上创建的仓库路径为"git@github.com :用户名/git-tutorial.git"。现在我们用 git remote add命令将它设置成本地仓库的远程仓库
bash
$ git remote add origin git@github.com:github-book/git-tutorial.git
按照上述格式执行git remote add命令之后,Git 会自动将git@github.com:github-book/git-tutorial.git远程仓库的名称设置为 origin(标识符)
1.8.2 git push(推送至远程仓库)
推送到master分支
如果想将当前分支下本地仓库中的内容推送给远程仓库,需要用到git push命令。现在假定我们在 master 分支下进行操作。
bash
$ git push -u origin master
Counting objects: 20, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (10/10), done.
Writing objects: 100% (20/20), 1.60 KiB, done.
Total 20 (delta 3), reused 0 (delta 0)
To git@github.com:github-book/git-tutorial.git
* [new branch]
master -> master
Branch master set up to track remote branch master from origin.
像这样执行 git push命令,当前分支的内容就会被推送给远程仓库origin 的 master 分支
推送到master以外的分支
除了 master 分支之外,远程仓库也可以创建其他分支。举个例子,我们在本地仓库中创建 feature-D 分支,并将它以同名形式 push 至远程仓库
bash
$ git checkout -b feature-D
Switched to a new branch 'feature-D'
我们在本地仓库中创建了 feature-D 分支,现在将它 push 给远程仓库并保持分支名称不变
bash
$ git push -u origin feature-D
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:github-book/git-tutorial.git
* [new branch]
feature-D -> feature-D
Branch feature-D set up to track remote branch feature-D from origin.
现在,在远程仓库的 GitHub 页面就可以查看到 feature-D 分支了
1.9 从远程仓库获取
1.9.1 git clone(获取远程仓库)
获取远程仓库
bash
$ git clone git@github.com:github-book/git-tutorial.git
Cloning into 'git-tutorial'...
remote: Counting objects: 20, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 20 (delta 3), reused 20 (delta 3)
Receiving objects: 100% (20/20), done.
Resolving deltas: 100% (3/3), done.
$ cd git-tutorial
执行 git clone命令后我们会默认处于 master 分支下,同时系统会自动将 origin 设置成该远程仓库的标识符。也就是说,当前本地仓库的 master 分支与 GitHub 端远程仓库(origin)的 master 分支在内容上是完全相同的
bash
$ git branch -a
* master #本地仓库
remotes/origin/HEAD -> origin/master #远程仓库
remotes/origin/feature-D
remotes/origin/master
我们用 git branch -a命令查看当前分支的相关信息。添加 -a参数可以同时显示本地仓库和远程仓库的分支信息。结果中显示了 remotes/origin/feature-D,证明我们的远程仓库中已经有了 feature-D 分支
获取远程的 feature-D 分支
bash
$ git checkout -b feature-D origin/feature-D #- b 参数的后面是本地仓库中新建分支的名称 紧接着为远程仓库分支名称
Branch feature-D set up to track remote branch feature-D from origin.
Switched to a new branch 'feature-D'
修改后将本地的 feature-D 分支提交更改
先执行 git add命令,再执行 git commit命令 等价于 git commit -am "提交信息"
bash
$ git commit -am "Add feature-D"
[feature-D ed9721e] Add feature-D
1 file changed, 1 insertion(+)
推送 feature-D 分支
bash
$ git push
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 281 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
To git@github.com:github-book/git-tutorial.git
ca0f98b..ed9721e feature-D -> feature-D
从远程仓库获取 feature-D 分支,在本地仓库中提交更改,再将feature-D 分支推送回远程仓库,通过这一系列操作,就可以与其他开发者相互合作,共同培育 feature-D 分支,实现某些功能
1.9.2 git pull (获取最新的远程仓库分支)
远程仓库的 feature-D 分支中更新了内容,将本地的 feature-D 分支更新到最新状态
bash
$ git pull origin feature-D
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 1), reused 3 (delta 1)
Unpacking objects: 100% (3/3), done.
From github.com:github-book/git-tutorial
* branch
feature-D -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
Fast-forwarded feature-D to ed9721e686f8c588e55ec6b8071b669f411486b8.
1.10 尝试Pull Request
Pull Request 是自己修改源代码后,请求对方仓库采纳该修改时采取的一种行为
现在假设我们在使用 GitHub 上的一款开源软件。在使用这款软件的过程中,我们偶然间发现了 BUG。为了继续使用软件,我们手动修复了这个 BUG。如果我们修改的这段代码能被该软件的开发仓库采纳,今后与我们同样使用这款软件的人就不会再遇到这个 BUG。为此,我们要第一时间发送 Pull Request
在 GitHub 上发送 Pull Request 后,接收方的仓库会创建一个附带源代码的 Issue,我们在这个 Issue 中记录详细内容。这就是 Pull Request.Pull Request 在网络上也常常被简称为 PR
发送过去的 Pull Request 是否被采纳,要由接收方仓库的管理者进行判断。一般只要代码没有问题,对方都会采纳。如果有问题,我们会收到评论。只要 Pull Request 被顺利采纳,我们就会成为这个项目的 Contributor(贡献者),我们编写的这段代码也将被全世界的人使用
不进行 Fork 直接从分支发送 Pull Request
一般说来,在 GitHub 上修改对方的代码时,需要先将仓库 Fork 到本地,然后再修改代码,发送 Pull Request。但是,如果用户对该仓库有编辑权限,则可以直接创建分支,从分支发送 Pull Request。利用这一设计,团队开发时不妨为每一名成员赋予编辑权限,免去 Fork 仓库的麻烦。这样,成员在有需要时就可以创建自己的分支,然后直接向 master分支等发送 Pull Request
仓库的维护