Contents
实际操作学习Git¶
基本操作¶
$ mkdir test_github
$ cd test_github/
$ git init
$ git status
$ 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
$ git add .
$ git commit -m "first commit..."
$ git status
$ git log
commit 3460fd1fa5245830b7ded8add0e1c4cbb6e65f62 (HEAD -> master)
Author: hujianli <hujiainli@126.com>
Date: Thu Nov 19 21:21:51 2020 +0800
first commit...
# 只显示提交的第一行
$ git log --pretty=short
# 只显示指定目录、文件的日志
$ git log README.md
# 显示文件的改动
$ git log -p
# 查看更改前后的差别
$ git diff
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory.
diff --git a/README.md b/README.md
index e69de29..8a4cfaa 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,2 @@
+##hello
+## my friend
# 查看工作树和暂存区的差别
$ git diff
# 查看工作树和最新提交的差别
$ git diff HEAD
$ git add README.md
$ git commit -m "Add index"
//成功查到了两次提交。
$ git log
分支的操作¶
//git branch——显示分支一览表
$ git branch
//创建、切换分支
$ git branch hujianli/dev
# 或者
$ git checkout -b hujianli/dev
//删除分支
$ git branch -d hujianli/dev
//切换分支
$ git checkout hujianli
Already on 'hujianli'
// 等同于
$ git branch hujiianli
$ git branch
* hujianli
master
$ cat README.md
##hello
## my friend
- branch A
$ git checkout master
Switched to branch 'master'
18793@DESKTOP-PMJTNGI MINGW64 /d/Github_01/test_github (master)
$ cat README.md
##hello
## my friend
//然后查看README.md文件,会发现README.md文件仍然保持原先的状态,并没有被添加文字。
//切换回上一个分支
$ git checkout -
Switched to branch 'hujianli'
$ git branch
* hujianli
●特性分支¶
特性分支顾名思义,是集中实现单一特性(主题),除此之外不进行任何作业的分支。在日常开发中,往往会创建数个特性分支,同时在此之外再保留一个随时可以发布软件的稳定分支。
基于特定主题的作业在特性分支中进行,主题完成后再与master分支合并。只要保持这样一个开发流程,就能保证master分支可以随时供人查看。这样一来,其他开发者也可以放心大胆地从master分支创建新的特性分支。
●主干分支¶
主干分支是刚才我们讲解的特性分支的原点,同时也是合并的终点。通常人们会用master分支作为主干分支。主干分支中并没有开发到一半的代码,可以随时供他人查看。
合并分支¶
$ git checkout master
$ git branch
hujianli
hujiianli
* master
$ git merge --no-ff hujianli
//随后编辑器会启动,用于录入合并提交的信息。
$ cat README.md
##hello
## my friend
- branch A
//git log --graph——以图表形式查看分支
$ git log --graph
* commit b9a21baa72ac01ca64c64a3d842c2fd1f80d09fc (HEAD -> master)
|\ Merge: f023abe faba748
| | Author: hujianli <hujiainli@126.com>
| | Date: Thu Nov 19 21:56:15 2020 +0800
| |
| | Merge branch 'hujianli'
| |
| | hujianli hello
| |
更改提交的操作¶
$ git log
$ git reset --hard 3b5beb47375901f7c81b08b526c5788caff93659
HEAD is now at 3b5beb4 Add index
18793@DESKTOP-PMJTNGI MINGW64 /d/Github_01/test_github (fix_branch)
$ cat README.md
##hello
## my friend
执行git reflog命令,查看当前仓库执行过的操作的日志
$ git reflog
e7a7c34 (HEAD -> fix_branch) HEAD@{0}: commit: fix B
3b5beb4 (master, hujiianli) HEAD@{1}: checkout: moving from master to fix_branch
3b5beb4 (master, hujiianli) HEAD@{2}: reset: moving to 3b5beb47375901f7c81b08b526c5788caff 93659
b9a21ba HEAD@{3}: checkout: moving from fix_branch to master
3b5beb4 (master, hujiianli) HEAD@{4}: reset: moving to 3b5beb47375901f7c81b08b526c5788caff 93659
faba748 (hujianli) HEAD@{5}: reset: moving to faba748cf8e7f192dd257d690c008b1fe37fe8a8
b9a21ba HEAD@{6}: checkout: moving from master to fix_branch
b9a21ba HEAD@{7}: merge hujianli: Merge made by the 'recursive' strategy.
f023abe HEAD@{8}: checkout: moving from hujianli to master
faba748 (hujianli) HEAD@{9}: commit: second commit....
f023abe HEAD@{10}: checkout: moving from master to hujianli
f023abe HEAD@{11}: merge hujianli: Fast-forward
3b5beb4 (master, hujiianli) HEAD@{12}: checkout: moving from master to master
3b5beb4 (master, hujiianli) HEAD@{13}: checkout: moving from master to master
3b5beb4 (master, hujiianli) HEAD@{14}: checkout: moving from hujianli to master
f023abe HEAD@{15}: checkout: moving from master to hujianli
3b5beb4 (master, hujiianli) HEAD@{16}: checkout: moving from hujianli to master
f023abe HEAD@{17}: commit: Add feature-A
3b5beb4 (master, hujiianli) HEAD@{18}: checkout: moving from hujianli to hujianli
3b5beb4 (master, hujiianli) HEAD@{19}: checkout: moving from master to hujianli
3b5beb4 (master, hujiianli) HEAD@{20}: commit: Add index
3460fd1 HEAD@{21}: commit (initial): first commit...
在日志中,我们可以看到commit、checkout、reset、merge等Git命令的执行记录。只要不进行Git的GC(Garbage Collection,垃圾回收),就可以通过日志随意调取近期的历史状态,就像给时间机器指定一个时间点,在过去未来中自由穿梭一般。即便开发者错误执行了Git操作,基本也都可以利用git reflog命令恢复到原先的状态。
我们将HEAD、暂存区、工作树进行时光倒流,恢复到f023abe这个时间点的状态。
$ git checkout master
Switched to branch 'master'
$ git reset --hard f023abe
HEAD is now at f023abe Add feature-A
18793@DESKTOP-PMJTNGI MINGW64 /d/Github_01/test_github (master)
$ cat README.md
##hello
## my friend
- branch A
// 再次进行时光倒流
$ git reset --hard e7a7c34
HEAD is now at e7a7c34 fix B
$ cat README.md
##hello
## my friend
fix -B
fix -B
fix -B
fix -B
fix -B
消除冲突¶
$ git merge --no-ff fix_branch
$ cat README.md
##hello
## my friend
<<<<<<< HEAD
fix -B
fix -B
fix -B
fix -B
fix -B
=======
- branch A
- branch A
- branch A
- branch A
- branch A
- branch A
>>>>>>> hujianli
// 这里发生了冲突
$ git merge --no-ff hujianli
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
=======以上的部分是当前HEAD的内容,以下的部分是要合并的fix-B分支中的内容。我们在编辑器中将其改成想要的样子。
$ cat README.md
##hello
## my friend
fix -B
fix -B
fix -B
fix -B
fix -B
- branch A
- branch A
- branch A
- branch A
- branch A
- branch A
本次修正让feature-A与fix-B的内容并存于文件之中。但是在实际的软件开发中,往往需要删除其中之一,所以各位在处理冲突时,务必要仔细分析冲突部分的内容后再行修改。
提交解决后的结果冲突解决后¶
执行git add命令与git commit命令。
$ git commit -m "Fix conflict"
[master 1524c36] Fix conflict
由于本次更改解决了冲突,所以提交信息记为“Fix conflict”。
修改提交信息¶
要修改上一条提交信息,可以使用git commit –amend命令。我们将上一条提交信息记为了“Fix conflict”,但它其实是fix-B分支的合并,解决合并时发生的冲突只是过程之一,这样标记实在不妥。于是,我们要修改这条提交信息。
$ git commit --amend
[master 29f2cf2] merge branch "fix_branch"
Date: Thu Nov 19 22:25:25 2020 +0800
随后会显示上面这条结果。现在执行git log –graph命令,可以看到提交日志中的相应内容也已经被修改。
$ git log --graph
* commit 29f2cf23a061e71e7e8380a6a7e1df857d68a378 (HEAD -> master)
|\ Merge: e7a7c34 faba748
| | Author: hujianli <hujiainli@126.com>
| | Date: Thu Nov 19 22:25:25 2020 +0800
| |
| | merge branch "fix_branch"
| |
| * commit faba748cf8e7f192dd257d690c008b1fe37fe8a8 (hujianli)
| | Author: hujianli <hujiainli@126.com>
| | Date: Thu Nov 19 21:55:28 2020 +0800
| |
| | second commit....
压缩历史¶
$ git checkout -b feature-C
Switched to a new branch 'feature-C'
$ git branch
* feature-C
fix_branch
hujianli
hujiianli
master
$ cat README.md
##hello
## my friend
- feature-A
- feature-B
- faeture-B
作为feature-C的功能实现,我们在README.md文件中添加一行文字,并且故意留下拼写错误,以便之后修正。
// 修正拼写错误
$ vim README.md
$ git diff
diff --git a/README.md b/README.md
index 4e49ea0..aec690f 100644
--- a/README.md
+++ b/README.md
@@ -3,4 +3,4 @@
- feature-A
- feature-B
-- faeture-B
+- feature-B
然后进行提交
$ git commit -am "Fix typo"
[feature-C 45b53fa] Fix typo
1 file changed, 1 insertion(+), 1 deletion(-)
更改历史
我们来更改历史。将“Fix typo”修正的内容与之前一次的提交合并,在历史记录中合并为一次完美的提交。为此,我们要用到git rebase命令。
$ git rebase -i HEAD~2
我们将6fba227的Fix typo的历史记录压缩到7a34294的Add feature-C里.
保存编辑器里的内容,关闭编辑器。
现在再查看提交日志时会发现Add feature-C的哈希值已经不是7a34294了,这证明提交已经被更改。
$ git log --graph
* commit e5495398de2f120815c593499926232250ef7a17 (HEAD -> feature-C)
| Author: hujianli <hujiainli@126.com>
| Date: Thu Nov 19 22:38:24 2020 +0800
|
| ADD feature-C
|
这样一来,Fix typo就从历史中被抹去,也就相当于Add feature-C中从来没有出现过拼写错误。这算是一种良性的历史改写。
合并至master分支feature-C分支的使命告一段落,我们将它与master分支合并。
$ git branch
* feature-C
fix_branch
hujianli
hujiianli
master
$ git checkout master
Switched to branch 'master'
$ git merge --no-ff feature-C
master分支整合了feature-C分支。开发进展顺利。
推送至远程仓库¶
在github上创建项目,然后本地进行推送
推送至master分支¶
目前github已经将master分支改为为main分支。主分支为main。
create a new repository on the command line
echo "# test_github" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:hujianli94/test_github.git
git push -u origin main
如果出现:git push error: failed to push some refs to报错!说明github仓库中的README文件不在本地代码目录中,
也就是说我们需要先将远程代码库中的任何文件先pull到本地代码库中,才能push新的代码到github代码库中。
使用如下命令:git pull --rebase origin master
然后再进行上传: git push -u origin master
问题解决。
push an existing repository from the command line
git remote add origin git@github.com:hujianli94/test_github.git
git branch -M main
git push -u origin main
推送至master以外的分支¶
$ git checkout feature-C
Switched to branch 'feature-C'
$ git push -u origin feature-C
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: Create a pull request for 'feature-C' on GitHub by visiting:
remote: https://github.com/hujianli94/test_github/pull/new/feature-C
remote:
To github.com:hujianli94/test_github.git
* [new branch] feature-C -> feature-C
Branch 'feature-C' set up to track remote branch 'feature-C' from 'origin'.
现在,在远程仓库的GitHub页面就可以查看到feature-C分支了
从远程仓库获取¶
git clone¶
获取远程仓库¶
$ git clone git@github.com:hujianli94/test_github.git
Cloning into 'test_github'...
remote: Enumerating objects: 22, done.
remote: Counting objects: 100% (22/22), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 22 (delta 3), reused 22 (delta 3), pack-reused 0
Receiving objects: 100% (22/22), done.
Resolving deltas: 100% (3/3), done.
执行git clone命令后我们会默认处于master分支下,同时系统会自动将origin设置成该远程仓库的标识符。也就是说,当前本地仓库的master分支与GitHub端远程仓库(origin)的master分支在内容上是完全相同的。
$ git branch -a
* main
remotes/origin/HEAD -> origin/main
remotes/origin/feature-C
remotes/origin/main
我们用git branch -a命令查看当前分支的相关信息。添加
-a参数可以同时显示本地仓库和远程仓库的分支信息。
获取远程的feature-C分支¶
$ git clone git@github.com:hujianli94/test_github.git
$ cd test_github
$ git checkout -b feature-C origin/feature-C
Switched to a new branch 'feature-C'
Branch 'feature-C' set up to track remote branch 'feature-C' from 'origin'.
$ git branch
* feature-C
向本地的feature-C分支提交更改¶
在README. md文件中添加一行文字,查看更改。
$ vim README.md
$ git diff
diff --git a/README.md b/README.md
index 4e49ea0..769c956 100644
--- a/README.md
+++ b/README.md
@@ -4,3 +4,6 @@
- feature-A
- feature-B
- faeture-B
+- faeture-B
+- faeture-D
+- faeture-E
$ git commit -am "ADD FEATURE-C"
[feature-C 5bef5e4] ADD FEATURE-C
1 file changed, 3 insertions(+)
$ git push
从远程仓库获取feature-C分支,在本地仓库中提交更改,再将feature-C分支推送回远程仓库,通过这一系列操作,就可以与其他开发者相互合作,共同培育feature-C分支,实现某些功能。
获取最新远程仓库分支¶
将本地的feature-C分支更新到最新状态
$ git pull origin feature-C
From github.com:hujianli94/test_github
* branch feature-C -> FETCH_HEAD
Already up to date.
如果两人同时修改同一部分的源代码,push时就很容易发生冲突,所以多名开发者在同一个分支中进行作业时,为减少冲突情况的发送,建议频繁的进行push和pull操作。