实际操作学习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操作。