【Git 入门】动手学习 Git
参考教程:Git教程 - 廖雪峰的官方网站
没有具体学习 10 使用 Gitee、11.3 搭建 Git服务器、12 使用 Source Tree。
1 安装
参考教程:Git 详细安装教程(详解 Git 安装过程的每一个步骤)
打开 Git Bash,设置个人信息:
1 |
|
2 创建版本库
创建空目录
learngit
:1
2
3
4
5$ cd Desktop/Project
$ mkdir learngit
$ cd learngit
$ pwd # 显示当前目录
/c/Users/21830/Desktop/Project/learngit把
learngit
变成 Git 可以管理的仓库:1
2$ git init
Initialized empty Git repository in C:/Users/21830/Desktop/Project/learngit/.git/列出目录所有内容:
1
2$ ls -ah # -a:显示所有文件,-h:以易读的格式显示文件大小
./ ../ .git/在
learngit
目录下编写一个readme.txt
文件:1
$ vim readme.txt # 之后按I进入插入模式来编辑,写好后按Esc退出,输入:wq保存文件并退出Vim
内容如下:
Git is a version control system. Git is free software.
将
readme.txt
添加并提交到仓库:1
2
3
4
5$ git add readme.txt # 可重复使用,添加多个文件
$ git commit -m "wrote a readme file" # -m: messages(提交说明)
[master (root-commit) 15ae68d] wrote a readme file
1 file changed, 2 insertions(+)
create mode 100644 readme.txt删除本地仓库:在对应目录下
rm -rf .git
后删除文件夹即可。
3 时光机穿梭
用 Vim 修改
readme.txt
,内容如下:Git is a distributed version control system. Git is free software.
查看仓库当前的状态:
1
2
3
4
5
6
7
8$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")查看
readme.txt
的修改内容:1
2
3
4
5
6
7
8
9$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.添加
readme.txt
并查看仓库状态:1
2
3
4
5
6$ git add readme.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: readme.txt提交
readme.txt
并查看仓库状态:1
2
3
4
5
6
7$ git commit -m "add distributed"
[master daaf95b] add distributed
1 file changed, 1 insertion(+), 1 deletion(-)
$ git status
On branch master
nothing to commit, working tree clean
3.1 版本回退
用 Vim 修改
readme.txt
,内容如下:Git is a distributed version control system. Git is free software distributed under the GPL.
提交
readme.txt
:1
2
3
4$ git add readme.txt
$ git commit -m "append GPL"
[master 97b0ca9] add GPL
1 file changed, 1 insertion(+), 1 deletion(-)查看历史提交日志:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18$ git log
commit 97b0ca9d0b01a5834c25e9aa54aff5d7d7150d73 (HEAD -> master)
Author: Xuan-Van <wuqi7137@qq.com>
Date: Sat Oct 26 17:53:32 2024 +0800
add GPL
commit daaf95bc4582d74baf9c4d267f7c6e838aaaa224
Author: Xuan-Van <wuqi7137@qq.com>
Date: Sat Oct 26 17:48:39 2024 +0800
add distributed
commit 15ae68d25889731562f9db61de8e45a75505cad3
Author: Xuan-Van <wuqi7137@qq.com>
Date: Sat Oct 26 17:30:57 2024 +0800
wrote a readme file简要查看从最近到最远的提交日志:
1
2
3
4$ git log --pretty=oneline
97b0ca9d0b01a5834c25e9aa54aff5d7d7150d73 (HEAD -> master) add GPL
daaf95bc4582d74baf9c4d267f7c6e838aaaa224 add distributed
15ae68d25889731562f9db61de8e45a75505cad3 wrote a readme file回退到上一个版本:
1
2$ git reset --hard HEAD^
HEAD is now at daaf95b add distributed- 最新版本是
HEAD
,上一个版本是HEAD^
,上上一个版本是HEAD^^
,上 n 个版本写是HEAD~n
。 --hard
会回退到上个版本的已提交状态,--soft
会回退到上个版本的未提交状态,--mixed
会回退到上个版本已添加但未提交的状态。
查看
readme.txt
来确认:
1
2
3$ cat readme.txt
Git is a distributed version control system.
Git is free software.- 最新版本是
查看当前版本库的提交日志:
1
2
3
4
5
6
7
8
9
10
11
12$ git log
commit daaf95bc4582d74baf9c4d267f7c6e838aaaa224 (HEAD -> master)
Author: Xuan-Van <wuqi7137@qq.com>
Date: Sat Oct 26 17:48:39 2024 +0800
add distributed
commit 15ae68d25889731562f9db61de8e45a75505cad3
Author: Xuan-Van <wuqi7137@qq.com>
Date: Sat Oct 26 17:30:57 2024 +0800
wrote a readme file回到指定版本(add GPL 版本):
1
2$ git reset --hard 97b0 # 版本号填写前几位
HEAD is now at 97b0ca9 add GPL查看
readme.txt
来确认:1
2
3$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.查看历史命令,以便确认未来版本:
1
2
3
4
5
6$ git reflog
97b0ca9 (HEAD -> master) HEAD@{0}: reset: moving to 97b0
daaf95b HEAD@{1}: reset: moving to HEAD^
97b0ca9 (HEAD -> master) HEAD@{2}: commit: add GPL
daaf95b HEAD@{3}: commit: add distributed
15ae68d HEAD@{4}: commit (initial): wrote a readme file
3.2 工作区和暂存区
- 工作区:可见的目录,一个文件夹
learngit
;版本库:工作区中的隐藏目录.git
,其中主要有暂存区stage
、主分支master
和指向master
的指针HEAD
。 git add
将文件修改添加到暂存区,git commit
将暂存区的所有内容提交到当前分支。- 向
readme.txt
添加一行内容:1
2
3
4
5$ echo Git has a mutable index called stage. >> readme.txt
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage. - 在工作区新增一个
LICENSE
文件,内容与readme.txt
一致:1
2
3
4
5$ cat readme.txt >> LICENSE
$ cat LICENSE
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage. - 查看仓库状态:
1
2
3
4
5
6
7
8
9
10
11
12$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
LICENSE
no changes added to commit (use "git add" and/or "git commit -a") - 添加两个文件到暂存区,查看仓库状态:
1
2
3
4
5
6
7
8$ git add readme.txt
$ git add LICENSE
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: LICENSE
modified: readme.txt - 提交暂存区的文件,查看仓库状态:
1
2
3
4
5
6
7
8$ git commit -m "understand how stage works"
[master 26c8682] understand how stage works
2 files changed, 4 insertions(+)
create mode 100644 LICENSE
$ git status
On branch master
nothing to commit, working tree clean
3.3 管理修改
- 向
readme.txt
添加一行内容:1
2
3
4
5
6$ echo Git tracks changes. >> readme.txt
$ cat readme.txt
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. - 添加到暂存区,查看仓库状态:
1
2
3
4
5
6$ git add readme.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: readme.txt - 再次修改
readme.txt
:1
2
3
4
5$ cat readme.txt
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. - 提交暂存区的文件,查看仓库状态:
1
2
3
4
5
6
7
8
9
10
11
12$ git commit -m "git tracks changes"
[master a914ff6] git tracks changes
1 file changed, 1 insertion(+)
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a") - 查看工作区和版本库里最新版本的区别:
1
2
3
4
5
6
7
8
9
10
11$ git diff HEAD -- readme.txt
diff --git a/readme.txt b/readme.txt
index 76d770f..a9c5755 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,4 @@
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.
+Git tracks changes of files. - 添加并提交文件,查看仓库状态:
1
2
3
4
5
6
7
8$ git add readme.txt
$ git commit -m "git tracks changes of ilfes"
[master f896b61] git tracks changes of ilfes
1 file changed, 1 insertion(+), 1 deletion(-)
$ git status
On branch master
nothing to commit, working tree clean
3.4 撤销修改
- 向
readme.txt
添加一行内容, 查看仓库状态:1
2
3
4
5
6
7
8
9$ echo My stupid boss still prefers SVN. >> readme.txt
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a") - 丢弃工作区的修改,让文件回到最近一次
git commit
或git add
时的状态:1
2
3
4
5
6$ git checkout -- readme.txt
$ cat readme.txt
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. - 向
readme.txt
添加一行内容,并添加到暂存区:1
2
3
4
5
6
7$ echo My stupid boss still prefers SVN. >> readme.txt
$ git add readme.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: readme.txt - 撤销暂存区的修改,丢弃工作区的修改:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17$ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git checkout -- readme.txt
$ git status
On branch master
nothing to commit, working tree clean - 如果错误的内容提交到了版本库,可以回退到上一个版本。
3.5 删除文件
- 添加一个
test.txt
到 Git 并提交:1
2
3
4
5
6$ echo Hello World! >> test.txt
$ git add test.txt
$ git commit -m "add test.txt"
[master e309196] add test.txt
1 file changed, 1 insertion(+)
create mode 100644 test.txt - 删除
test.txt
:1
2
3
4
5
6
7
8
9$ rm test.txt
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: test.txt
no changes added to commit (use "git add" and/or "git commit -a") - 从版本库中删除并提交,这时
git rm
和git add
的效果是一样的:1
2
3
4
5
6
7$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master 49a82cf] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt - 如果手动误删,可以用
git checkout -- test.txt
把误删的文件恢复到最新版本,但是会丢失最近一次提交后你修改的内容。从来没有被添加到版本库就被删除的文件,是无法恢复的。
4 远程仓库
- 创建 SSH Key: 然后一路回车,接着到用户主目录中找到
1
$ ssh-keygen -t rsa -C "wuqi7137@qq.com"
.ssh
目录,里面有id_rsa
(私钥,禁止泄露)和id_rsa.pub
(公钥)两个文件。 - 添加 SSH Key:
graph LR A[登录 GitHub] --> B[Settings] B --> C[SSH and GPG keys] C --> D[New SSH key] D --> E["Title填写“SSH Key”<br>Key粘贴id_rsa.pub中的内容"] E --> F[Add SSH key]
- 验证 SSH 成功连接:
1
2$ ssh -T git@github.com
Hi Xuan-Van! You've successfully authenticated, but GitHub does not provide shell access.
4.1 添加远程库
在 GitHub 上新建一个 Repository,名称为
learngit
,并与本地learngit
进行关联,origin
是默认习惯命名:1
$ git remote add origin git@github.com:Xuan-Van/learngit.git
报错:fatal: not a git repository (or any of the parent directories): .git
原因:文件路径不对,应该到learngit
目录中执行。
还可以使用 HTTPS 协议进行连接,将git@github.com:Xuan-Van/learngit.git
替换为https://github.com/Xuan-Van/learngit
即可。把本地库的所有内容推送到远程库上:
1
2
3
4
5
6
7
8
9
10
11$ git push -u origin master
Enumerating objects: 22, done.
Counting objects: 100% (22/22), done.
Delta compression using up to 16 threads
Compressing objects: 100% (18/18), done.
Writing objects: 100% (22/22), 1.82 KiB | 622.00 KiB/s, done.
Total 22 (delta 6), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (6/6), done.
To github.com:Xuan-Van/learngit.git
* [new branch] master -> master
branch 'master' set up to track 'origin/master'.git push -u origin master
是第一次推送时使用的,不但会把本地的 master 分支内容推送的远程新的 master 分支,还会把本地的 master 分支和远程的 master 分支关联起来。报错:
To github.com:Xuan-Van/learngit.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to ‘github.com:Xuan-Van/learngit.git’
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: ‘git pull’ before pushing again.
hint: See the ‘Note about fast-forwards’ in ‘git push –help’ for details.
原因:在尝试推送更改到远程仓库时,远程仓库已经包含了本地没有的更改。git push origin master
把本地 master 分支的最新修改推送至 GitHub。
查看远程库信息:
1
2
3$ git remote -v
origin git@github.com:Xuan-Van/learngit.git (fetch)
origin git@github.com:Xuan-Van/learngit.git (push)使用
git remote rm origin
来解除本地和远程的绑定关系。
4.2 从远程库克隆
- 在 GitHub 上新建一个 Repository,名称为
gitskills
,勾选Add a README file
,GitHub 自动创建一个README.md
文件。 - 克隆一个本地库: 可以使用
1
2
3
4
5
6$ git clone git@github.com:Xuan-Van/gitskills.git
Cloning into 'gitskills'...
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.git clone GitHub的Repository网址
来克隆自己或他人的远程库。 - 克隆成功:
1
2
3$ cd gitskills/
$ ls
README.md
4.3 使用 GitHub
- 在 GitHub 上,可以任意 Fork 开源仓库;
- 自己拥有 Fork 后的仓库的读写权限;
- 可以推送 pull request 给官方仓库来贡献代码。
5 分支管理
5.1 创建与合并分支
创建
dev
分支并切换到dev
分支:1
2$ git checkout -b dev
Switched to a new branch 'dev'该命令相当于:
1
2
3$ git branch dev # 创建
$ git checkout dev # 切换
Switched to branch 'dev'用
git branch
命令查看当前分支*
:1
2
3$ git branch
* dev
master修改
readme.txt
,并提交:1
2
3
4
5$ echo Creating a new branch is quick. >> readme.txt
$ git add readme.txt
$ git commit -m "branch test"
[dev cbcac43] branch test
1 file changed, 1 insertion(+)切换回
master
分支,查看readme.txt
文件:1
2
3
4
5
6
7
8
9$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
$ cat readme.txt
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.把
dev
分支的工作成果合并到master
分支上,,查看readme.txt
文件:1
2
3
4
5
6
7
8
9
10
11
12$ git merge dev # 合并指定分支到当前分支
Updating 49a82cf..cbcac43
Fast-forward # 快件模式,直接把 master 指向 dev 的当前提交
readme.txt | 1 +
1 file changed, 1 insertion(+)
$ cat readme.txt
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.
Creating a new branch is quick.删除
dev
分支,查看分支:1
2
3
4
5$ git branch -d dev
Deleted branch dev (was cbcac43).
$ git branch
* masterswitch
命令:- 创建并切换到新的
dev
分支:1
2$ git switch -c dev
Switched to a new branch 'dev' - 直接切换到已有的
master
分支:1
2$ git switch master
Switched to branch 'master'
- 创建并切换到新的
5.2 解决冲突
准备新的
feature1
分支:1
2$ git switch -c feature1
Switched to a new branch 'feature1'修改
readme.txt
最后一行,改为:Creating a new branch is quick AND simple.
在
feature1
分支上提交:1
2
3
4$ git add readme.txt
$ git commit -m "AND simple"
[feature1 3bc9c41] AND simple
1 file changed, 1 insertion(+), 1 deletion(-)切换到
master
分支:1
2
3
4$ git switch master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)在
master
分支上把readme.txt
文件的最后一行改为:Creating a new branch is quick & simple.
提交:
1
2
3
4$ git add readme.txt
$ git commit -m "& simple"
[master 4d30980] & simple
1 file changed, 1 insertion(+), 1 deletion(-)合并冲突:
1
2
3
4$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.查看仓库状态:
1
2
3
4
5
6
7
8
9
10
11
12
13
14$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")查看
readme.txt
:1
2
3
4
5
6
7
8
9
10$ cat readme.txt
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 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. Creating a new branch is quick and simple.
再提交:
1
2
3$ git add readme.txt
$ git commit -m "conflict fixed"
[master 1b8779e] conflict fixed用带参数的
git log
也可以看到分支的合并情况:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15$ git log --graph --pretty=oneline --abbrev-commit
* 1b8779e (HEAD -> master) conflict fixed
|\
| * 3bc9c41 (feature1) AND simple
* | 4d30980 & simple
|/
* cbcac43 branch test
* 49a82cf (origin/master) remove test.txt
* e309196 add test.txt
* f896b61 git tracks changes of ilfes
* a914ff6 git tracks changes
* 26c8682 understand how stage works
* 97b0ca9 add GPL
* daaf95b add distributed
* 15ae68d wrote a readme file删除
feature1
分支:1
2$ git branch -d feature1
Deleted branch feature1 (was 3bc9c41).
5.3 分支管理策略
创建并切换
dev
分支:1
2$ git switch -c dev
Switched to a new branch 'dev'修改
readme.txt
文件,并提交一个新的commit
:1
2
3
4$ git add readme.txt
$ git commit -m "add merge"
[dev 8cca272] add merge
1 file changed, 1 insertion(+)切换回
master
:1
2$ git switch master
Switched to branch 'master'准备合并
dev
分支,--no-ff
表示禁用Fast forward
,可以看出合并历史:1
2
3
4$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'ort' strategy.
readme.txt | 1 +
1 file changed, 1 insertion(+)用
git log
查看分支历史:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19$ git log --graph --pretty=oneline --abbrev-commit
* 98f7914 (HEAD -> master) merge with no-ff
|\
| * 8cca272 (dev) add merge
|/
* 1b8779e conflict fixed
|\
| * 3bc9c41 AND simple
* | 4d30980 & simple
|/
* cbcac43 branch test
* 49a82cf (origin/master) remove test.txt
* e309196 add test.txt
* f896b61 git tracks changes of ilfes
* a914ff6 git tracks changes
* 26c8682 understand how stage works
* 97b0ca9 add GPL
* daaf95b add distributed
* 15ae68d wrote a readme filemaster
分支是非常稳定的,仅用来发布新版本;dev
分支是不稳定的,用来日常开发。团队成员在dev
分支上创建自己的分支,往dev
分支上合并。
5.4 Bug 分支
- 当前
dev
上的任务还未提交:1
2
3
4
5
6
7
8
9
10$ git status
On branch dev
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: hello.py
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt - 用
git stash
把当前工作现场“储藏”起来,等以后恢复现场后继续工作:1
2
3
4
5
6$ git stash
Saved working directory and index state WIP on dev: 8cca272 add merge
$ git status
On branch dev
nothing to commit, working tree clean - 在
master
分支上修复 bug,就从master
创建临时分支:1
2
3
4
5
6
7$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
$ git checkout -b issue-101
Switched to a new branch 'issue-101' - 修复 bug,把“Git is free software …”改为“Git is a free software …”,然后提交:
1
2
3
4$ git add readme.txt
$ git commit -m "fix bug 101"
[issue-101 092f44e] fix bug 101
1 file changed, 1 insertion(+), 1 deletion(-) - 修复完成后,切换到
master
分支,并完成合并,最后删除issue-101
分支:1
2
3
4
5
6
7
8
9
10
11
12$ git switch master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
$ git merge --no-ff -m "merged bug fix 101" issue-101
Merge made by the 'ort' strategy.
readme.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
$ git branch -d issue-101
Deleted branch issue-101 (was 092f44e). - 回到
dev
分支工作:1
2
3
4
5
6$ git switch dev
Switched to branch 'dev'
$ git status
On branch dev
nothing to commit, working tree clean - 查看工作现场:
1
2$ git stash list
stash@{0}: WIP on dev: 8cca272 add merge - 恢复工作现场:
git stash apply
:恢复后,stash
内容并不删除,需要用git stash drop
来删除;git stash pop
,恢复的同时把stash
内容也删了:1
2
3
4
5
6
7
8
9
10
11
12$ git stash pop
On branch dev
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: hello.py
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt
Dropped refs/stash@{0} (303e10edcbd261d38e8ebffb64db91d3914b2e9e)
- 再用
git stash list
查看,就看不到任何stash
内容了。可以多次stash
,恢复的时候先用git stash list
查看,然后用命令git stash apply stash@{0}
恢复指定的stash
。 - 在
dev
分支上修复同样的 bug:1
2
3
4$ git cherry-pick 092f44e # fix bug 101 的commit号
[dev 9ed458e] fix bug 101
Date: Sun Nov 10 15:19:44 2024 +0800
1 file changed, 1 insertion(+), 1 deletion(-)
5.5 Feature 分支
- 每添加一个新功能,最好新建一个
feature
分支:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15$ git switch -c feature-vulcan
Switched to a new branch 'feature-vulcan'
$ vim vulcan.py
$ git add vulcan.py
$ git status
On branch feature-vulcan
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: vulcan.py
$ git commit -m "add feature vulcan"
[feature-vulcan 3372ec0] add feature vulcan
1 file changed, 1 insertion(+)
create mode 100644 vulcan.py - 切回
dev
,取消新功能:1
2
3
4
5
6
7$ git switch dev
Switched to branch 'dev'
$ git branch -d feature-vulcan
error: the branch 'feature-vulcan' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D feature-vulcan'
hint: Disable this message with "git config advice.forceDeleteBranch false" - 删除失败,
feature-vulcan
分支还没有被合并,如果删除,将丢失掉修改。如果要强行删除,需要使用大写的-D
参数:1
2$ git branch -D feature-vulcan
Deleted branch feature-vulcan (was 3372ec0).
5.6 多人协作
- 查看远程库的信息:
1
2$ git remote
origin # 远程仓库的默认名称 - 显示更详细的信息:
1
2
3$ git remote -v
origin git@github.com:Xuan-Van/learngit.git (fetch)
origin git@github.com:Xuan-Van/learngit.git (push) - 推送分支,把该分支上的所有本地提交推送到远程库:
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$ git push origin master
Enumerating objects: 22, done.
Counting objects: 100% (22/22), done.
Delta compression using up to 16 threads
Compressing objects: 100% (20/20), done.
Writing objects: 100% (20/20), 1.74 KiB | 890.00 KiB/s, done.
Total 20 (delta 9), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (9/9), completed with 1 local object.
To github.com:Xuan-Van/learngit.git
49a82cf..42ab936 master -> master
$ git push origin dev
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 16 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 561 bytes | 561.00 KiB/s, done.
Total 6 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (2/2), completed with 1 local object.
remote:
remote: Create a pull request for 'dev' on GitHub by visiting
remote: https://github.com/Xuan-Van/learngit/pull/new/de
remote:
To github.com:Xuan-Van/learngit.git
* [new branch] dev -> dev报错:
Connection reset by 20.205.243.166 port 22 fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
参考教程:坑:ssh: connect to host github.com port 22: Connection refused
原因:22 端口被占用,改用 443 端口,在~/.ssh
下添加config
文件,内容为:Host github.com Hostname ssh.github.com Port 443
之后执行
ssh -T git@github.com
来测试和 GitHub 的通信是否正常。
master
分支是主分支,要时刻与远程同步;dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;bug
分支只用于在本地修复bug,就没必要推到远程了;feature
分支是否推到远程,取决于是否和团队成员合作在上面开发。 - 抓取分支,将远程仓库克隆到本地:
1
2
3
4
5
6
7
8
9
10$ git clone git@github.com:Xuan-Van/gitskills.git
Cloning into 'gitskills'...
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.
$ cd gitskills/
$ git branch
* main - 要在
dev
分支上开发,就必须创建远程origin
的dev
分支到本地:1
2
3$ git checkout -b dev origin/dev
branch 'dev' set up to track 'origin/dev'.
Switched to a new branch 'dev' - 在
dev
上继续修改,然后把dev
分支push
到远程:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16$ vim env.txt
$ git add env.txt
$ git commit -m "add env"
[dev d7a32aa] add env
1 file changed, 1 insertion(+)
create mode 100644 env.txt
$ git push origin dev
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 16 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 283 bytes | 283.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To github.com:Xuan-Van/gitskills.git
096ff39..d7a32aa dev -> dev - 如果团队成员 A 已经向
origin/dev
分支推送了提交,而碰巧团队成员 B 也对同样的文件作了修改,并试图推送:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17$ cat env.txt
env
$ git add env.txt
$ git commit -m "add new env"
[dev 9e457d3] add new env
1 file changed, 1 insertion(+), 1 deletion(-)
$ git push origin dev
To github.com:Xuan-Van/gitskills.git
! [rejected] dev -> dev (fetch first)
error: failed to push some refs to 'github.com:Xuan-Van/gitskills.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details. - 出现冲突,推送失败,先抓取最新提交:
1
2
3
4
5
6
7
8
9
10
11$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (3/3), 914 bytes | 17.00 KiB/s, done.
From github.com:Xuan-Van/gitskills
d7a32aa..ae0f3cf dev -> origin/dev
Auto-merging env.txt
CONFLICT (content): Merge conflict in env.txt
Automatic merge failed; fix conflicts and then commit the result.可能因为没有指定本地
dev
分支与远程origin/dev
分支的链接而出现抓取失败(no tracking information),需要设置dev
和origin/dev
的链接:git branch --set-upstream-to=origin/dev dev
。 - 解决冲突后提交,并上传到远程仓库:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22$ cat env.txt
<<<<<<< HEAD
env
=======
env.
>>>>>>> ae0f3cf38645e15cae7e3c2349d03a71385838a9
$ vim env.txt
$ git add env.txt
$ git commit -m "fix env conflict"
[dev dc107ec] fix env conflict
$ git push origin dev
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 16 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 396 bytes | 396.00 KiB/s, done.
Total 4 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (1/1), done.
To github.com:Xuan-Van/gitskills.git
ae0f3cf..dc107ec dev -> dev
5.7 Rebase
提交了两次
hello.py
后的分支形状: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$ git log --graph --pretty=oneline --abbrev-commit
* 84091cc (HEAD -> master) del the first line
* aa35a6f add 'the'
* 1d3ab8a (origin/master) del author
* 6bdaa2d del hello
* d5af4d8 merge branch 'master' of github
|\
| * 2bd33ff Create hello.py
* | 395b305 add author
* | e5f6e7a add comment
|/
* 42ab936 merged bug fix 101
|\
| * 092f44e fix bug 101
|/
* 98f7914 merge with no-ff
|\
| * 8cca272 add merge
|/
* 1b8779e conflict fixed
|\
| * 3bc9c41 AND simple
* | 4d30980 & simple
|/
* cbcac43 branch test
* 49a82cf remove test.txt
* e309196 add test.txt
* f896b61 git tracks changes of ilfes
* a914ff6 git tracks changes
* 26c8682 understand how stage works
* 97b0ca9 add GPL
* daaf95b add distributed
* 15ae68d wrote a readme file尝试推送本地分支:
1
2
3
4
5
6
7
8
9$ git push origin master
To github.com:Xuan-Van/learngit.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'github.com:Xuan-Van/learngit.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.推送失败,先抓取:
1
2
3
4
5
6
7
8
9
10
11$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (3/3), 971 bytes | 25.00 KiB/s, done.
From github.com:Xuan-Van/learngit
1d3ab8a..e45f5f4 master -> origin/master
Merge made by the 'ort' strategy.
hello.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)解决冲突,查看仓库状态:
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
36
37
38
39
40
41
42
43
44$ git status
On branch master
Your branch is ahead of 'origin/master' by 3 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
$ git log --graph --pretty=oneline --abbrev-commit
* d691b01 (HEAD -> master) Merge branch 'master' of github
|\
| * e45f5f4 (origin/master) print(Hello World!")
* | 84091cc del the first line
* | aa35a6f add 'the'
|/
* 1d3ab8a del author
* 6bdaa2d del hello
* d5af4d8 merge branch 'master' of github
|\
| * 2bd33ff Create hello.py
* | 395b305 add author
* | e5f6e7a add comment
|/
* 42ab936 merged bug fix 101
|\
| * 092f44e fix bug 101
|/
* 98f7914 merge with no-ff
|\
| * 8cca272 add merge
|/
* 1b8779e conflict fixed
|\
| * 3bc9c41 AND simple
* | 4d30980 & simple
|/
* cbcac43 branch test
* 49a82cf remove test.txt
* e309196 add test.txt
* f896b61 git tracks changes of ilfes
* a914ff6 git tracks changes
* 26c8682 understand how stage works
* 97b0ca9 add GPL
* daaf95b add distributed
* 15ae68d wrote a readme file把分叉的提交历史“整理”成一条直线,看上去更直观:
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
36
37$ git rebase
Successfully rebased and updated refs/heads/master.
$ git log --graph --pretty=oneline --abbrev-commit
* 796188b (HEAD -> master) del the first line
* 127236a add 'the'
* e45f5f4 (origin/master) print(Hello World!")
* 1d3ab8a del author
* 6bdaa2d del hello
* d5af4d8 merge branch 'master' of github
|\
| * 2bd33ff Create hello.py
* | 395b305 add author
* | e5f6e7a add comment
|/
* 42ab936 merged bug fix 101
|\
| * 092f44e fix bug 101
|/
* 98f7914 merge with no-ff
|\
| * 8cca272 add merge
|/
* 1b8779e conflict fixed
|\
| * 3bc9c41 AND simple
* | 4d30980 & simple
|/
* cbcac43 branch test
* 49a82cf remove test.txt
* e309196 add test.txt
* f896b61 git tracks changes of ilfes
* a914ff6 git tracks changes
* 26c8682 understand how stage works
* 97b0ca9 add GPL
* daaf95b add distributed
* 15ae68d wrote a readme file报错:可能会因为本地和远程都对同一个文件进行了修改而无法
git rebase
,需要解决冲突后git add 冲突文件名
再git rebase --continue
即可。把本地分支推送到远程:
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
36
37
38
39
40
41
42
43
44
45$ git push origin master
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 16 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 544 bytes | 544.00 KiB/s, done.
Total 6 (delta 4), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (4/4), completed with 2 local objects.
To github.com:Xuan-Van/learngit.git
e45f5f4..796188b master -> master
$ git log --graph --pretty=oneline --abbrev-commit
* 796188b (HEAD -> master, origin/master) del the first line
* 127236a add 'the'
* e45f5f4 print(Hello World!")
* 1d3ab8a del author
* 6bdaa2d del hello
* d5af4d8 merge branch 'master' of github
|\
| * 2bd33ff Create hello.py
* | 395b305 add author
* | e5f6e7a add comment
|/
* 42ab936 merged bug fix 101
|\
| * 092f44e fix bug 101
|/
* 98f7914 merge with no-ff
|\
| * 8cca272 add merge
|/
* 1b8779e conflict fixed
|\
| * 3bc9c41 AND simple
* | 4d30980 & simple
|/
* cbcac43 branch test
* 49a82cf remove test.txt
* e309196 add test.txt
* f896b61 git tracks changes of ilfes
* a914ff6 git tracks changes
* 26c8682 understand how stage works
* 97b0ca9 add GPL
* daaf95b add distributed
* 15ae68d wrote a readme file
6 标签管理
6.1 创建标签
在需要打标签的分支上打一个新标签:
1
$ git tag v1.0
查看所有标签:
1
2$ git tag
v1.0向历史提交打标签:
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
36
37
38
39$ git log --graph --pretty=oneline --abbrev-commit
* 796188b (HEAD -> master, tag: v1.0, origin/master) del the first line
* 127236a add 'the'
* e45f5f4 print(Hello World!")
* 1d3ab8a del author
* 6bdaa2d del hello
* d5af4d8 merge branch 'master' of github
|\
| * 2bd33ff Create hello.py
* | 395b305 add author
* | e5f6e7a add comment
|/
* 42ab936 merged bug fix 101
|\
| * 092f44e fix bug 101
|/
* 98f7914 merge with no-ff
|\
| * 8cca272 add merge
|/
* 1b8779e conflict fixed
|\
| * 3bc9c41 AND simple
* | 4d30980 & simple
|/
* cbcac43 branch test
* 49a82cf remove test.txt
* e309196 add test.txt
* f896b61 git tracks changes of ilfes
* a914ff6 git tracks changes
* 26c8682 understand how stage works
* 97b0ca9 add GPL
* daaf95b add distributed
* 15ae68d wrote a readme file
$ git tag v0.9 d5af4d8
$ git tag
v0.9
v1.0查看标签信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16$ git show v0.9
commit d5af4d8c2540a7a9aeae09fe8d9a5814c9d43ced (tag: v0.9)
Merge: 395b305 2bd33ff
Author: Xuan-Van <wuqi7137@qq.com>
Date: Sun Nov 10 20:29:14 2024 +0800
merge branch 'master' of github
diff --cc hello.py
index 3793d4e,ce01362..fd2de04
--- a/hello.py
+++ b/hello.py
@@@ -1,2 -1,1 +1,3 @@@
+ hello
+comment
+author创建带有说明的标签,用
-a
指定标签名,-m
指定说明文字:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22$ git tag -a v0.1 -m "version 0.1 released" 97b0
$ git show v0.1
tag v0.1
Tagger: Xuan-Van <wuqi7137@qq.com>
Date: Mon Nov 11 09:53:05 2024 +0800
version 0.1 released
commit 97b0ca9d0b01a5834c25e9aa54aff5d7d7150d73 (tag: v0.1)
Author: Xuan-Van <wuqi7137@qq.com>
Date: Sat Oct 26 17:53:32 2024 +0800
add GPL
diff --git a/readme.txt b/readme.txt
index 9247db6..8443d23 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
Git is a distributed version control system.
-Git is free software.
+Git is free software distributed under the GPL.标签总是和某个 commit 挂钩。如果这个 commit 既出现在
master
分支,又出现在dev
分支,那么在这两个分支上都可以看到这个标签。
6.2 操作标签
删除标签:
1
2$ git tag -d v0.1
Deleted tag 'v0.1' (was 947237b)推送某个标签到远程:
1
2
3
4$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To github.com:Xuan-Van/learngit.git
* [new tag] v1.0 -> v1.0推送所有标签到远程:
1
2
3
4$ git push origin --tags
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To github.com:Xuan-Van/learngit.git
* [new tag] v0.9 -> v0.9删除本地标签和远程标签:
1
2
3
4
5
6$ git tag -d v0.9
Deleted tag 'v0.9' (was d5af4d8)
$ git push origin :refs/tags/v0.9
To github.com:Xuan-Van/learngit.git
- [deleted] v0.9
7 自定义 Git
git config --global color.ui true
让 Git 显示颜色,使命令输出看起来更醒目。
7.1 忽略特殊文件
- 忽略文件的原则是:
- 忽略操作系统自动生成的文件,比如缩略图等;
- 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
- 忽略带有敏感信息的配置文件,比如存放口令的配置文件。
忽略Windows自动生成的垃圾文件:
# Windows: Thumbs.db ehthumbs.db Desktop.ini
忽略 Python 编译产生的
.pyc
、.pyo
、dist
等文件或目录:# Python: *.py[cod] *.so *.egg *.egg-info dist build
加上自己定义的文件,最终得到一个完整的
.gitignore
文件:# Windows: Thumbs.db ehthumbs.db Desktop.ini # Python: *.py[cod] *.so *.egg *.egg-info dist build # My configurations: db.ini deploy_key_rsa
不需要从头写
.gitignore
文件,只需要组合 github/gitignore 的各种配置文件就可以使用了。.gitignore
文件本身应该提交给 Git 管理,这样可以确保所有人在同一项目下都使用相同的.gitignore
文件。检验.gitignore
的标准是git status
命令是不是说working directory clean
。被
.gitignore
忽略的文件无法添加到 Git,需要使用git add -f 文件名
来强制添加,或者使用git check-ignore -v 文件名
来检查.gitignore
中的问题并修订。当编写了规则排除了部分文件时:
# 排除所有.开头的隐藏文件: .* # 排除所有.class文件: *.class
但是
.*
这个规则把.gitignore
也排除了,并且App.class
需要被添加到版本库,但是被*.class
规则排除了。可以添加两条例外规则:# 排除所有.开头的隐藏文件: .* # 排除所有.class文件: *.class # 不排除.gitignore和App.class: !.gitignore !App.class
可以通过 Git Ignore Online Generator 在线生成
.gitignore
文件并直接下载。.gitignore
文件放在哪个目录下,就对哪个目录(包括子目录)起作用。
7.2 配置别名
- 用
st
表示status
,co
表示checkout
,ci
表示commit
,br
表示branch
:1
2
3
4$ git config --global alias.st status
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch--global
参数是全局参数,也就是这些命令在这台电脑的所有 Git 仓库下都有用。如果不加,那只针对当前的仓库起作用。 - 用
unstage
来表示reset HEAD
(把暂存区的修改撤销掉,重新放回工作区),用last
来表示log -1
(显示最后一次提交信息):1
2$ git config --global alias.unstage 'reset HEAD'
$ git config --global alias.last 'log -1' - 甚至配置长命令:
1
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
- 每个仓库的 Git 配置文件都放在
.git/config
文件中:别名就在1
2
3
4
5
6
7
8
9
10
11
12
13
14$ cat .git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "origin"]
url = git@github.com:Xuan-Van/learngit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master[alias]
后面,要删除别名,直接把对应的行删掉即可。 - 当前用户的 Git 配置文件放在用户主目录下的一个隐藏文件
.gitconfig
中:配置别名也可以直接修改这个文件,如果改错了,可以删掉文件重新通过命令配置,或者直接删掉配置文件错误的那一行。1
2
3
4
5
6
7
8
9$ cd ~/
$ cat .gitconfig
[user]
name = Xuan-Van
email = wuqi7137@qq.com
[gui]
recentrepo = C:/Users/21830/Desktop/Project/learngit
[color]
ui = true
7.3 报错
- 使用 HTTPS 协议克隆时出现:
SSL certificate problem: unable to get local issuer certificate
解决:git config --global http.sslbackend schannel
作用:这条命令设置了 Git 在进行 HTTPS 请求时使用的 SSL 后端为 schannel。schannel 是 Windows 操作系统内置的安全支持提供者(Security Support Provider, SSP)。当 Git 需要进行安全的 HTTPS 通信时,它将使用 Windows 的 schannel 而不是 OpenSSL。这在某些情况下可能有助于提高性能或解决与 OpenSSL 相关的问题。 - 【完美解决】GitHub连接超时问题 Recv failure: Connection was reset