Git:操作

Git工作流程

一般工作流程如下:

  • 将Git的一个存储库克隆为工作副本。
  • 可以通过添加/编辑文件修改工作副本。
  • 如有必要,还可以通过让其他开发人员一起来更改/更新工作副本。
  • 在提交之前查看更改。
  • 提交更改:如果一切正常,那么将您的更改推送到存储库。
  • 提交后,如果意识到某些错误并修改错误后,则将最后一个正确的修改提交并将推送到存储库。

下面显示的是工作流程的图示 -

img

gerrit

提交代码到Gerrit

  1. git stash。将自己的代码进行隐藏

  2. git pull –rebase 拉取其他人的修改,进行合并最新的修改

  3. git stash pop 将自己的代码合并进入最新的分支当中

  4. 若他人与自己修改了同一个文件则进行冲突解决

  5. git add //需要提交的文件

  6. git commit -m “注释”

  7. git push origin HEAD:refs/for/<分支名>

代码提交之后需要修改

  1. git stash

  2. git pull –rebase

  3. git stash pop

  4. 冲突解决

  5. git add

  6. git commit –amend

    • vim操作退出
  7. git push origin HEAD:refs/for/<分支名>

  8. PS. 如果不使用amend会导致提交两个code review 到 gerrit上面

  9. 如果提交了两次commit ,将gerrit上面的最新的一次提交abandon

  10. 同时本地执行 git log,git reset <前一次提交的commit id>

  11. reset之后再执行 5 开始的步骤

查看更改git log

适用场景

  • 查看git的历史提交
    • git log -n(查看前n条)
  • 查看一次的详细提交
    • git show commitId

如何查看 Git 存储库的文件和提交记录,并对存储库中的文件作修改和提交。

比如,我们查看提交详细信息后,需要修改代码,或添加更多的代码,或者对比提交结果。

下面使用git log命令查看日志详细信息。

1
$ git log

执行上面命令后,得到以下输出结果 -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ git log
commit be24e214620fa072efa877e1967571731c465884
Author: your_name <your_email@mail.com>
Date: Fri Jul 7 18:58:16 2017 +0800

??mark

commit 5eccf92e28eae94ec5fce7c687f6f92bf32a6a8d
Author: your_name <your_email@mail.com>
Date: Fri Jul 7 18:52:06 2017 +0800

this is main.py file commit mark use -m option

commit 6e5f31067466795c522b01692871f202c26ff948
Author: your_name <your_email@mail.com>
Date: Fri Jul 7 18:42:43 2017 +0800

this is main.py file commit mark without use "-m" option

commit 290342c270bc90f861ccc3d83afa920169e3b07e
Author: Maxsu <769728683@qq.com>
Date: Fri Jul 7 16:55:12 2017 +0800

Initial commit

使用git show命令查看某一次提交详细信息。 git show命令采用SHA-1提交ID作为参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ git show be24e214620fa072efa877e1967571731c465884
commit be24e214620fa072efa877e1967571731c465884
Author: your_name <your_email@mail.com>
Date: Fri Jul 7 18:58:16 2017 +0800

??mark

diff --git a/main.py b/main.py
index 91a1389..657c8d0 100644
--- a/main.py
+++ b/main.py
@@ -3,3 +3,5 @@

print ("Life is short, you need Python !")

+# this is a comment line
+

上面显示的结果中,可以看到符号 “+“ ,表示添加的内容。如果有 “-”则表示删除的内容,现在我们打开 main.py ,把注释行去掉并定义一个变量。修改后的 main.py 的内容如下所示 -

1
2
3
4
5
#!/usr/bin/python3
#coding=utf-8
print ("Life is short, you need Python !")
a = 10
b = 20

然后使用命令:git stauts 查看当前工作区状态 -

1
2
3
4
5
6
7
8
9
10
11
12
$ git status
On branch master
Your branch is ahead of 'origin/master' by 3 commits.
(use "git push" to publish your local commits)

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: main.py

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

测试代码后,通过运行git diff命令来回顾他的更改。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git diff
diff --git a/main.py b/main.py
index 95053b4..a4f953e 100644
--- a/main.py
+++ b/main.py
@@ -4,4 +4,6 @@
print ("Life is short, you need Python !")


-number = 100
+a = 10
+
+b = 20

可以看到符号 “+“ (绿色),表示添加的内容。如果有 “-”(红色)则表示删除的内容。执行的效果如下所示 -

img

现在使用以下命令将文件:main.py 添加到 git 暂存区,然后提交代码完成 -

1
2
$ git add main.py
$ git commit -m "define two var a & b "

最近修改的代码已提交完成。

提交修改git commit

  • 增补提交,会使用与当前提交节点相同的父节点进行一次新的提交,旧的提交将会被取消
    • git commit –amend

合并commit

  • 要从HEAD版本呢开始合并过往的1-3条comit
    • git rebase -i HEAD~3(-i是指不需要合并的commit的hash值)
    • 或者是git rebase -i commitId

执行命令后会出现vim

1
2
3
pick 3ca6ec3   '注释**********'
pick 1b40566 '注释*********'
pick 53f244a '注释**********'
  • pick 的意思是要会执行这个 commit
  • squash(简写为s) 的意思是这个 commit 会被合并到前一个commit,因此修改后两个的pick为s
1
2
3
pick 3ca6ec3   '注释**********'
s 1b40566 '注释*********'
s 53f244a '注释**********'

:wq保存退出,此时git会进行合并,并弹出提示信息

1
2
3
4
5
6
7
8
# This is a combination of 3 commits.
# This is the 1st commit message:
update3  
# This is the commit message #2: 
update2  
# This is the commit message #3: 
update1 
# Please enter the commit message for your changes. Lines starting

修改我们最终需要的Commit msg。即改为,:wq保存退出

1
2
3
# This is a combination of 3 commits.
合并提交的文本msg
# Please enter the commit message for your changes. Lines starting

查看log则有

1
2
3
commit 4a51759fae9bbd84904029473fe09f8a77f143ed
Author: pan
Date: Sun Apr 22 08:54:55 2018 +0800 合并提交的文本msg

注意事项:如果这个过程中有操作错误,可以使用 git rebase --abort来撤销修改,回到没有开始操作合并之前的状态。

推送操作git push

1
$ git push origin master

上述命令将产生以下结果:

1
2
3
4
5
6
7
8
9
10
$ git push origin master
Username for 'http://git.oschina.net': 76972883@qq.com <输入帐号>
Password for 'http://76972883@qq.com@git.oschina.net': <输入登录密码>
Counting objects: 13, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (12/12), 1.20 KiB | 0 bytes/s, done.
Total 12 (delta 3), reused 0 (delta 0)
To http://git.oschina.net/yiibai/sample.git
290342c..51de0f0 master -> master

隐藏操作Git Stash

应用场景

假设您正在为产品新的功能编写/实现代码,当正在编写代码时,突然出现软件客户端升级。这时,您必须将新编写的功能代码保留几个小时然后去处理升级的问题。在这段时间内不能提交代码,也不能丢弃您的代码更改。 所以需要一些临时等待一段时间,您可以存储部分更改,然后再提交它。

使用

在Git中,隐藏操作将使您能够修改跟踪文件,阶段更改,并将其保存在一系列未完成的更改中,并可以随时重新应用。

1
2
3
4
5
6
7
8
9
10
11
$ git status
On branch master
Your branch is up-to-date with 'origin/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: main.py

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

现在,要切换分支以进行客户升级,但不想提交一直在做的工作; 那么可以把当前工作的改变隐藏起来。 要将一个新的存根推到堆栈上,运行git stash命令。

1
2
3
$ git stash
Saved working directory and index state WIP on master: ef07ab5 synchronized with the remote repository
HEAD is now at ef07ab5 synchronized with the remote repository

现在,工作目录是干净的,所有更改都保存在堆栈中。 现在使用git status命令来查看当前工作区状态。

1
2
3
4
5
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean

现在,可以安全地切换分支并在其他地方工作。通过使用git stash list命令来查看已存在更改的列表。

1
2
$ git stash list
stash@{0}: WIP on master: ef07ab5 synchronized with the remote repository

假设您已经解决了客户升级问题,想要重新开始新的功能的代码编写,查找上次没有写完成的代码,只需执行git stash pop命令即可从堆栈中删除更改并将其放置在当前工作目录中。

1
2
3
4
5
$ git status -s

Administrator@MY-PC /D/worksp/sample (master)

[jerry@CentOS project]$ git stash pop

上述命令将产生以下结果:

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
$ git stash pop
On branch master
Your branch is up-to-date with 'origin/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: main.py

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (e713780380632c142ed5833a9087aca883a826fa)

Administrator@MY-PC /D/worksp/sample (master)

$ git status
On branch master
Your branch is up-to-date with 'origin/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: main.py

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

可以看到,工作区中修改的文件(main.py)又显示了。现在我们就可以继续编写上次编写了未完成的代码。

隐藏部分文件

git stash --keep-index只会隐藏没有被add的文件

修正错误

撤销暂存

适用场景

  • 当我们将不想暂存的文件被git add到了索引后,想要回退取消
    • git reset HEAD <file>

恢复未提交的更改git checkout

适用场景

  • 假设我们不小心修改(删除)了本地存储库中的一个文件,此时想撤销这些修改
    • 为了处理这种情况,我们可以使用git checkout命令。可以使用此命令来还原文件的内容。

为了更好的演示,我们首先在 sample/src 目录下创建一个文件:string.py ,其代码如下所示 -

1
2
3
4
5
6
7
#!/usr/bin/python3

var1 = 'Hello World!'
var2 = "Python Programming"

print ("var1[0]: ", var1[0])
print ("var2[1:5]: ", var2[1:5]) # 切片加索引

并使用以下命令将此文件推送到远程存储库 -

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
$ pwd
/D/worksp/sample

Administrator@MY-PC /D/worksp/sample (master)
$ git add src/

Administrator@MY-PC /D/worksp/sample (master)
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

new file: src/string.py


Administrator@MY-PC /D/worksp/sample (master)
$ git add src/string.py

Administrator@MY-PC /D/worksp/sample (master)
$ git commit -m "add new file string.py"
[master 44ea8e4] add new file string.py
1 file changed, 7 insertions(+)
create mode 100644 src/string.py

Administrator@MY-PC /D/worksp/sample (master)
$ git push origin master
Username for 'http://git.oschina.net': 769728683@qq.com
Password for 'http://769728683@qq.com@git.oschina.net':
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 443 bytes | 0 bytes/s, done.
Total 4 (delta 0), reused 0 (delta 0)

现在,已经将string.py添加到远程存储库中了。

假设我们不小心/或者有心修改了本地存储库中的一个文件。但现在不想要这些修改的内容了,也就是说想要撤销修改。要处理这种情况,那么可以使用git checkout命令。可以使用此命令来还原文件的内容。

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
$ pwd
/D/worksp/sample

Administrator@MY-PC /D/worksp/sample (master)
$ git status
On branch master
Your branch is up-to-date with 'origin/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: src/string.py

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

Administrator@MY-PC /D/worksp/sample (master)
$ git checkout src/string.py

Administrator@MY-PC /D/worksp/sample (master)
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean

此外,还可以使用git checkout命令从本地存储库获取已删除的文件。假设我们从本地存储库中删除一个文件,我们想要恢复这个文件。那么可以通过使用git checkout命令来实现这一点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ ls -l
total 1
-rw-r--r-- 1 Administ Administ 57 Jul 7 05:37 README.md
drwxr-xr-x 1 Administ Administ 0 Jul 10 21:16 src

Administrator@MY-PC /D/worksp/sample (master)
$ cd src/

Administrator@MY-PC /D/worksp/sample/src (master)
$ ls -l
total 1
-rwxr-xr-x 1 Administ Administ 156 Jul 10 21:16 string.py

Administrator@MY-PC /D/worksp/sample/src (master)
$ rm string.py

Administrator@MY-PC /D/worksp/sample/src (master)
$ ls -l
total 0

Administrator@MY-PC /D/worksp/sample/src (master)
$ git status -s
D string.py

Git在文件名前显示字母D, 这表示该文件已从本地存储库中删除。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git checkout string.py

Administrator@MY-PC /D/worksp/sample/src (master)
$ ls -l
total 1
-rwxr-xr-x 1 Administ Administ 156 Jul 10 21:24 string.py

Administrator@MY-PC /D/worksp/sample/src (master)
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean

注意:可以在提交操作之前执行这些操作。

用Git复位移动头指针(即回滚)

适用场景

  • 当经过更改,并且执行commit后,并且决定删除更改,回退到之前的某个commit。
    • git reset –hard commitId
  • 当代码提交了之后发现没有提交完整,或者想要重新编辑一下提交的信息
    • git reset –soft HEAD^。即重置HEAD指针,但不改变文件。

经过少量更改后,可以决定删除这些更改。 git reset命令用于复位或恢复更改。 我们可以执行三种不同类型的复位操作。

下图显示了git reset命令的图示。

git reset命令之前 -

img

git reset命令之后 -

img

—soft选项

每个分支都有一个HEAD指针,它指向最新的提交。 如果用--soft选项后跟提交ID的Git reset命令,那么它将仅重置HEAD指针而不会破坏任何东西。

.git/refs/heads/master文件存储HEAD指针的提交ID。 可使用git log -1命令验证它。

1
2
3
4
5
6
$ pwd
/D/worksp/sample

Administrator@MY-PC /D/worksp/sample (master)
$ cat .git/refs/heads/master
44ea8e47307b47c9a80b44360e09f973e79312b0

现在,查看最新前两个的提交ID,最近一次ID将与上述提交ID一致。

1
2
3
4
5
6
7
8
9
10
11
12
$ git log -2
commit 44ea8e47307b47c9a80b44360e09f973e79312b0
Author: maxsu <your_email@mail.com>
Date: Mon Jul 10 21:09:35 2017 +0800

add new file string.py

commit 7d8162db36723b8523c56ad658a07808ae7fb64c
Author: minsu <minsu@yiibai.com>
Date: Mon Jul 10 17:51:11 2017 -0700

remove/delete module.py

下面我们重置HEAD指针。

1
git reset -soft 7d8162db36723b8523c56ad658a07808ae7fb64c

现在,只需将HEAD指针重新设置一个位置。现在查看.git/refs/heads/master文件的内容。

1
2
3
Administrator@MY-PC /D/worksp/sample (master)
$ cat .git/refs/heads/master
7d8162db36723b8523c56ad658a07808ae7fb64c

来自文件的提交ID已更改,现在通过查看提交消息进行验证。

1
2
3
4
5
6
7
8
9
10
11
12
$ git log -2
commit 7d8162db36723b8523c56ad658a07808ae7fb64c
Author: minsu <minsu@yiibai.com>
Date: Mon Jul 10 17:51:11 2017 -0700

remove/delete module.py

commit 6bdbf8219c60d8da9ad352c23628600faaefbe13
Author: maxsu <your_email@mail.com>
Date: Mon Jul 10 20:34:28 2017 +0800

renamed main.py to module.py

mixed选项

使用--mixed选项的Git重置将从尚未提交的暂存区域还原这些更改。它仅从暂存区域恢复更改。对文件的工作副本进行的实际更改不受影响。 默认Git复位等效于执行git reset - mixed

hard选项

如果使用--hard选项与Git重置命令,它将清除分段区域; 它会将HEAD指针重置为特定提交ID的最新提交,并删除本地文件更改。

让我们查看提交ID。

1
2
3
4
5
6
7
8
9
10
11
Administrator@MY-PC /D/worksp/sample (master)
$ pwd
/D/worksp/sample

Administrator@MY-PC /D/worksp/sample (master)
$ git log -1
commit 7d8162db36723b8523c56ad658a07808ae7fb64c
Author: minsu <minsu@yiibai.com>
Date: Mon Jul 10 17:51:11 2017 -0700

remove/delete module.py

通过在文件开头添加单行注释来修改文件或者往文件里添加其它代码。

1
2
3
4
5
6
$ head -2 src/string.py
#!/usr/bin/python3

Administrator@MY-PC /D/worksp/sample (master)
$ git status -s
M src/string.py

将修改的文件添加到暂存区域,并使用git status命令进行验证。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git add src/string.py

Administrator@MY-PC /D/worksp/sample (master)
$ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 1 and 1 different commit each, respectively.
(use "git pull" to merge the remote branch into yours)

Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified: src/string.py

Git状态显示该文件存在于暂存区域中。 现在,重置HEAD与--hard选项。

1
2
3
4
$ git reset --hard 7d8162db36723b8523c56ad658a07808ae7fb64c
HEAD is now at 7d8162d remove/delete module.py

Administrator@MY-PC /D/worksp/sample (master)

git reset命令成功,这将从分段区域还原文件,并删除对文件所做的任何本地更改。

1
2
Administrator@MY-PC /D/worksp/sample (master)
$ git status -s

Git状态显示该文件已从暂存区域还原,当前恢复到了删除 moudle.py 时的版本了。

处理冲突

  • 使用idea的处理冲突工具
  • 注意自己的commit要尽量少一些,不然rebase很麻烦
  • 如果自己的commit很多,则先将自己的rebase为一个commit之后在进行拉取

参考

  1. 易百教程