0%

如何使用Git

Git头图

Git 是一个开源的分布式版本控制软件。


安装

Windows

Git 下载页:Git for Windows

Linux

1
2
3
4
5
# CentOS/Red Hat
$ yum install -y git

# Debian
$ apt-get install git

其他 Linux 发行版安装 Git 的方式参考:Git for Linux

Quick Start

在 GitHub 上面创建一个新的存储库后会看到一个快速上手的说明,以 GitHub 的这个说明为例子介绍下如何使用 Git。

从零开始创建一个新的存储库,并推送到 GitHub:

test/
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
# 创建一个说明文件
# GitHub建议为每个存储库创建一个说明文件,这个说明文件会显示在GitHub存储库的页面中
$ echo "# test" >> README.md

# 创建一个空的存储库
# 会在当前目录下生成一个.git目录,创建一个没有任何提交的初始分支
$ git init

# 将说明文件的内容添加到暂存区(索引),作为下次提交的内容
# 可以理解为在正式提交前将变更内容放在一个“暂存区”中
$ git add README.md

# 创建一个包含索引当前内容和描述这次改动信息的新提交
# 提交“暂存区”中的记录
$ git commit -m "first commit"

# 将分支名称改为main【没必要】
# git默认的分支名称为master,GitHub原先也使用master作为默认分支名
# 但受BLM运动的影响,GitHub于2020年10月开始将默认分支名称改为了main
$ git branch -M main

# 将git@github.com:sannaha/test.git添加为远程存储库,别名为origin
$ git remote add origin git@github.com:sannaha/test.git

# 将main分支推送给origin远程存储库
$ git push -u origin main

版本库

存储库(repository)又名仓库,这个仓库里面的所有文件都可以由 Git 管理,每个文件的修改、删除,Git都能跟踪。

创建版本库

  • git init:初始化仓库
1
2
3
# 在当前目录创建版本库
$ git init
Initialized empty Git repository in E:/workspace/GitProject/GitTest/.git/

添加文件到版本库

  • git add filename:添加文件到暂存区
  • git commit -m "message":提交暂存区记录到仓库
1
2
3
4
5
6
7
8
# 把文件添加到暂存区
$ git add README.md

# 把暂存区中的记录提交到本地仓库,编写提交说明
$ git commit -m "create a readme file"
[master (root-commit) 408dfd7] create a readme file
1 file changed, 1 insertion(+)
create mode 100644 README.md

查看仓库状态

当我们对文件做了一些修改,可以查看仓库的状态,以及做了哪些改动。

  • git status:查看工作区的状态
  • git diff:查看修改了哪些内容
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
# 查看仓库当前的状态,是否有未提交的修改
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: README.md

no changes added to commit (use "git add" and/or "git commit -a")

# 查看文件做了哪些修改
$ git diff README.md
diff --git a/README.md b/README.md
index 0de7e3e..e8b5125 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
-Hello Git.
\ No newline at end of file
+Hello Git.
+Write a new line.
\ No newline at end of file

# 将修改进行提交
$ git add README.md
$ git commit -m "add new line"
[master 3f7e457] add new line
1 file changed, 2 insertions(+), 1 deletion(-)

版本控制

版本回退

  • git log:查看提交历史
  • git reflog:查看命令历史
  • git reset --hard commit_id:回退到指定版本
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
# 查看提交历史
$ git log
commit 3f7e4571d4dbdcb30c3eba89908d728cb13f11cf (HEAD -> master)
Author: sannaha <3annaha@gmail.com>
Date: Wed May 8 23:48:46 2019 +0800

add new line

commit 408dfd792d146a0e2d8f4ce3d69c4d5aa4f345e0
Author: sannaha <3annaha@gmail.com>
Date: Wed May 8 23:41:38 2019 +0800

create a readme file

# 版本回退到上个版本
$ git reset --hard HEAD^
HEAD is now at 408dfd7 create a readme file

# 版本回退到上上个版本
$ git reset --hard HEAD^^

# 版本回退到上100个版本
$ git reset --hard HEAD~100

#版本回退到指定版本
$ git reset --hard 3f7e
HEAD is now at 3f7e457 add new line

# 查看命令历史
$ git reflog
3f7e457 (HEAD -> master) HEAD@{0}: reset: moving to 3f7e
408dfd7 HEAD@{1}: reset: moving to HEAD^
3f7e457 (HEAD -> master) HEAD@{2}: commit: add new line
408dfd7 HEAD@{3}: commit (initial): create a readme file

管理修改

  • git checkout -- filename:丢弃工作区的修改
  • git reset HEAD filename:把暂存区的修改撤销掉

删除文件

  • git rm:删除文件
1
2
3
4
5
6
7
8
9
10
11
# 使用rm删除工作区中的文件
$ git add test.txt
$ git commit -m "add test.txt"
$ rm test.txt

# 删错了?用版本库里的版本替换工作区的版本
$ git checkout -- test.txt

# 使用git rm从删除版本库中的文件
$ git rm test.txt
$ git commit -m "remove test.txt"

远程仓库

TODO List:

  • GitHub,Gitee。
  • SSH免密

廖雪峰-远程仓库

提交到远程仓库

1
2
3
4
5
6
7
8
9
10
# 关联远程仓库
git remote add origin git@gitee.com:sannaha/IDEACommit.git
git remote add origin git@github.com:sannaha/SSHTest.git
git remote add origin ssh://git@192.168.153.100/home/git/firstdepo

# 第一次推送master分支到远程仓库,使用-u参数关联本地的master分支和远程的master分支
git push -u origin master

# 之后推送
git push origin master

从远程仓库克隆

1
2
3
# 从远程仓库克隆一个本地库
git clone git@gitee.com:sannaha/IDEACommit.git
git clone root@192.168.153.100:/home/git/sshtest.git

私服

TODO List:

  • 安装git
  • 创建git用户,用来运行git服务
  • 创建证书登录
  • 初始化Git仓库

分支管理

创建与合并分支

创建分支

1
2
3
4
5
6
# 创建dev分支,并切换到dev分支
git checkout -b dev

# 相当于以下两条命令,创建分支,切换分支
git branch dev
git checkout dev

看当前分支

1
2
3
4
# 看当前分支,带*号
$ git branch
* dev
master

合并分支

把 dev 分支合并到master分支上,执行“快速合并”,把HEAD指针直接指向dev了,无冲突

1
2
3
4
5
# 切换到master分支
$ git checkout master

# 合并dev分支
$ git merge dev

删除分支

1
2
# 删除dev分支
$ git branch -d dev

创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支

解决冲突

准备新的feature1分支

1
$ git checkout -b feature1

修改 readme.txt,在 feature1 分支上提交:

1
$ git add readme.txt

切换到 master 分支:

1
$ git checkout master

在 master 分支上修改 readme.txt 文件,提交

1
$ git add readme.txt 

现在,master 分支和 feature1 分支各自都分别有新的提交,会有冲突
尝试合并

1
$ git merge feature1

Git 告诉我们,readme.txt 文件存在冲突,必须手动解决冲突后再提交。
git status 也可以告诉我们冲突的文件

1
$ git status

我们也可以直接查看 readme.txt 的内容

1
2
3
4
5
6
7
8
9
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature1

Git 用 <<<<<<<=======>>>>>>> 标记出不同分支的内容

我们修改如下后保存(人工解决冲突)

再提交:

1
2
$ git add readme.txt 
$ git commit -m "conflict fixed"

用带参数的 git log 也可以看到分支的合并情况

1
2
3
4
5
6
7
8
9
$ git log --graph --pretty=oneline --abbrev-commit

* cf810e4 (HEAD -> master) conflict fixed
|\
| * 14096d0 (feature1) AND simple
* | 5dc6824 & simple
|/
* b17d20e branch test
...

最后,删除feature1分支:

1
$ git branch -d feature1

网络相关问题

通过代理拉取GitHub代码

从 GitHub 拉取代码速度比较慢,如果有 Shadowsocks 等软件,可以开启代理提升连接速度 。Shadowsocks 默认在 1080 端口开启了 Socks5 代理,为了兼容只支持 HTTP 代理的应用,1080 端口也支持 HTTP 代理。

  • 对于形如 https://github.com/apache/kafka.git 的链接,设置 HTTP 代理或 Socks5 代理即可:
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
# 设置HTTP代理,代理所有http/https流量
$ git config --global http.proxy http://127.0.0.1:1080
# 查看代理配置是否生效
$ git config --global --get http.proxy
http://127.0.0.1:1080
# 取消代理
git config --global --unset http.proxy

# 设置HTTP代理,仅代理GitHub的http/https流量(推荐)
$ git config --global http.https://github.com.proxy http://127.0.0.1:1080
# 查看代理配置是否生效
$ git config --global --get http.https://github.com.proxy
https://127.0.0.1:1080
# 取消代理GitHub
$ git config --global --unset http.https://github.com.proxy

# 设置Socks5代理,代理所有流量。socks5h表示远端DNS解析,socks5表示本地DNS解析
$ git config --global http.proxy socks5h://127.0.0.1:1080
# 查看Socks5代理配置是否生效
$ git config --global --get http.proxy
socks5h://127.0.0.1:1080
# 取消代理
git config --global --unset http.proxy

# 设置Socks5代理,仅代理GitHub的流量(推荐)
$ git config --global http.https://github.com.proxy socks5h://127.0.0.1:1080
# 查看Socks5代理配置是否生效
$ git config --global --get http.https://github.com.proxy
socks5h://127.0.0.1:1080
# 取消代理GitHub
$ git config --global --unset http.https://github.com.proxy
  • 对于形如 git@github.com:apache/kafka.git 的链接,需要进行更多的设置。

    1. .ssh 目录下创建配置文件 config

      1
      $ vi ~/.ssh/config
    2. config 中填入以下配置,注意替换为实际路径:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      ProxyCommand connect -S 127.0.0.1:1080 -a none %h %p

      Host github.com
      User git
      Port 22
      Hostname github.com
      IdentityFile "C:\Users\SANNAHA\.ssh\id_rsa"
      TCPKeepAlive yes
      ServerAliveInterval 600
      IPQoS=throughput
      ServerAliveCountMax 120

      Host ssh.github.com
      User git
      Port 443
      Hostname ssh.github.com
      IdentityFile "C:\Users\SANNAHA\.ssh\id_rsa"
      TCPKeepAlive yes
      ServerAliveInterval 600
      IPQoS=throughput
      ServerAliveCountMax 120
    3. 设置 HTTP 代理或 Socks5 代理,过程同上。

改善国内服务器访问GitHub速度

双十一上车了国内便宜量大腾讯的轻量云服务器,没想对 GitHub 等网站的访问那么困难,用起来太痛苦了。

修改hosts文件

可以修改 hosts 文件,添加国内服务器能够 ping 通 GitHub 的 IP 地址。

  1. 访问 www.ipaddress.com
  2. 查询 GitHub 使用的 IP,如果解析到多个 IP 地址,选择丢包和延迟较低的即可:
1
2
3
4
5
github.com
assets-cdn.github.com
github.global.ssl.fastly.net
codeload.github.com
raw.githubusercontent.com
  1. 填入 hosts 文件:
/etc/hosts
1
2
3
4
5
140.82.114.4 github.com
185.199.109.153 assets-cdn.github.com
199.232.69.194 github.global.ssl.fastly.net
140.82.112.9 codeload.github.com
185.199.108.133 raw.githubusercontent.com

使用镜像

除了修改 hosts 文件外,也可以使用 GitHub 的国内镜像网站,在 clone 时将 github.com 替换为 github.com.cnpmjs.org 等镜像站的域名即可:

1
2
3
4
5
- git clone https://github.com/powerline/fonts.git
+ git clone https://github.com.cnpmjs.org/powerline/fonts.git
git clone https://github.com/EsunR/Blog-Index.git

https://github.com.cnpmjs.org/EsunR/Blog-Index.git

删除提交历史

之前看到过实习生把密码等敏感信息提交到 GitHub 的新闻,没想到有一天自己也会在个人项目上中招。

ComitHistory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 查看最近3次提交日志,需要删除的是最近两次提交(2a56c50,3e91787)
$ git log --pretty=format:"%h %s" HEAD~3..HEAD
3e91787 update README and key mapping
2a56c50 Add startMuMu Button,shutdown timer and increase button size
01b40dc update README

# 使用git rebase删除这两行内容
$ git rebase -i HEAD~3
Successfully rebased and updated refs/heads/master.

# 查看提交日志
$ git log --pretty=format:"%h %s" HEAD~3..HEAD
01b40dc update README
00efbd8 update for Arknights GUI version
c03a1a9 add Arknights GUI version

# 强制推送到GitHub
$ git push origin master --force

GitRebase

工具

可视化命令工具 https://ndpsoftware.com/git-cheatsheet.html#loc=index;

git-pretty


参考资料

廖雪峰的Git教程
git 设置和取消代理
如何在同一端口实现socks5与http

https://git-scm.com/docs

  • 本文作者: SANNAHA
  • 本文链接: https://sannaha.moe/Git/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!