Git命令


前言

安装完Git先配置用户名和账号

# 配置用户名
git config --global user.name "username"    //( "username"是自己的账户名)
# 配置邮箱
git config --global user.email "username@email.com"     //("username@email.com"注册账号时用的邮箱)

配置完成后输入git config --global --list查看

$ git config --global --list
user.name=xxxxx
user.email=xxxxx@qq.com

一、创建版本库

1、新建一个目录(文件夹),这个目录里的所有文件都可以被Git管理起来(注意:目录尽量不要包含中文)

$ mkdir DocPowerPoints
$ cd DocPowerPoints
$ pwd
/d/DocPowerPoints

2、通过git init命令把这个目录变成Git可以管理的仓库

$ git init
Initialized empty Git repository in D:/DocPowerPoints/.git/

3、把文件添加到版本库,一定要放到DocPowerPoints或者其子目录下,不然Git找不到。添加一个readme.txt文件,里边包含两行

Git is a version control system.
Git is free software.

4、接下来分为两步,第一步用git add告诉Git,把文件添加到仓库(add可以跟多个文件,也可反复多次使用)

$ git add readme.txt

执行上面命令没有任何显示,然后第二步,用命令git commit告诉Git,把文件提交到仓库:-m后面跟的是本次提交的说明;

$ git commit -m "wrote a readme file"
[master (root-commit) eaadf4e] wrote a readme file
 1 file changed, 2 insertions(+)
 create mode 100644 readme.txt

二、使用步骤

1.修改文件

1、我们继续修改readme.txt文件,改成如下内容:

Git is a distributed version control system.
Git is free software.

2、现在,运行git status命令看看结果:

$ 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.txt

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

git status命令可以让我们时刻掌握仓库当前的状态,上面的命令输出告诉我们,readme.txt被修改过了,但还没有准备提交的修改。想看看具体修改了什么内容可以用git diff这个命令看看:

$ git diff
diff --git a/readme.txt b/readme.txt
index d8036c1..013b5bc 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.
\ No newline at end of file

知道了对readme.txt作了什么修改后,再把它提交到仓库就放心多了,提交修改和提交新文件是一样的两步,第一步是git add:

$ git add readme.txt

同样没有任何输出。在执行第二步git commit之前,我们再运行git status看看当前仓库的状态:

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   readme.txt

git status告诉我们,将要被提交的修改包括readme.txt,下一步,就可以放心地提交了:

$ git commit -m "add distributed"
[master 3d33a89] add distributed
 1 file changed, 1 insertion(+), 1 deletion(-)

提交后,我们再用git status命令看看仓库的当前状态:

$ git status
On branch master
nothing to commit, working tree clean

2.版本回退

1、再次修改readme.txt文件如下:

Git is a distributed version control system.
Git is free software distributed under the GPL.

2、然后尝试提交:

$ git add readme.txt
$ git commit -m "append GPL"
[master 1094adb] append GPL
 1 file changed, 1 insertion(+), 1 deletion(-)

此时已经有三个版本被提交到Git仓库了。版本1:wrote a readme file;版本2:add distributed;版本3:append GPL。在Git中,我们用git log命令查看这些记录:

$ git log
commit 2fbfd19e683b6b5603a5accfe63fdafba16ceb49 (HEAD -> master)
Author: dgdqqxxx <2521257530@qq.com>
Date:   Wed Feb 9 16:23:21 2022 +0800

    append GPL

commit 3d33a890a6192e8794ef583f10872227d1999afd
Author: dgdqqxxx <2521257530@qq.com>
Date:   Wed Feb 9 16:14:24 2022 +0800

    add distributed

commit 092abe77901e1a0d5633dd33e6b4c76b1d157f42
Author: dgdqqxxx <2521257530@qq.com>
Date:   Wed Feb 9 11:56:28 2022 +0800

    wrote a readme file

git log命令显示从最近到最远的提交日志,我们可以看到3次提交,最近的一次是append GPL,上一次是add distributed,最早的一次是wrote a readme file。
如果嫌输出信息太多,看得眼花缭乱的,可以试试加上–pretty=oneline参数:

$ git log --pretty=oneline
2fbfd19e683b6b5603a5accfe63fdafba16ceb49 (HEAD -> master) append GPL
3d33a890a6192e8794ef583f10872227d1999afd add distributed
092abe77901e1a0d5633dd33e6b4c76b1d157f42 wrote a readme file

3、好了,如果现在我们准备把readme.txt回退到上一个版本,也就是add distributed的那个版本,怎么做呢?首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交2fbfd…,上一个版本就是HEAD^ ,上上一个版本就是HEAD^^ ,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。现在,我们要把当前版本append GPL回退到上一个版本add distributed,就可以使用git reset命令:

$ git reset --hard HEAD^
HEAD is now at 3d33a89 add distributed

让我们用git log再看看现在版本库的状态:

$ git log
commit 3d33a890a6192e8794ef583f10872227d1999afd (HEAD -> master)
Author: dgdqqxxx <2521257530@qq.com>
Date:   Wed Feb 9 16:14:24 2022 +0800

    add distributed

commit 092abe77901e1a0d5633dd33e6b4c76b1d157f42
Author: dgdqqxxx <2521257530@qq.com>
Date:   Wed Feb 9 11:56:28 2022 +0800

    wrote a readme file

最新的那个版本append GPL已经看不到了!想再回去怎么办?办法其实还是有的,只要上面的命令行窗口还没有被关掉,你就可以顺着往上找啊找啊,找到那个append GPL的commit id是2fbfd…,于是就可以指定回到未来的某个版本:

$ git reset --hard 2fbfd
HEAD is now at 2fbfd19 append GPL

现在假如你回退到了某个版本,关掉了电脑,想恢复到新版本找不到新版本的commit id怎么办?在Git中,总是有后悔药可以吃的。当你用$ git reset --hard HEAD^回退到add distributed版本时,再想恢复到append GPL,就必须找到append GPL的commit id。Git提供了一个命令git reflog用来记录你的每一次命令:

$ git reflog
2fbfd19 (HEAD -> master) HEAD@{0}: reset: moving to 2fbfd
3d33a89 HEAD@{1}: reset: moving to HEAD^
2fbfd19 (HEAD -> master) HEAD@{2}: commit: append GPL
3d33a89 HEAD@{3}: commit: add distributed
092abe7 HEAD@{4}: commit (initial): wrote a readme file

终于舒了口气,从输出可知,append GPL的commit id是2fbfd19,现在,你又可以乘坐时光机回到未来了

3.撤销修改

1、如果你在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.
My stupid boss still prefers SVN.

添加完这句话后readme.txt还没有放到暂存区,则命令git checkout – file可以丢弃工作区的修改::

$ git checkout -- readme.txt

命令git checkout – readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。总之,就是让这个文件回到最近一次git commit或git add时的状态。现在,看看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.

文件内容果然复原了。git checkout – file命令中的–很重要,没有–,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令。

$ 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.

2、如果你在readme.txt中添加了一行,还add到了暂存区,但还未commit,则可以用命令git reset HEAD 可以把暂存区的修改撤销掉(unstage),重新放回工作区:

$ git reset HEAD readme.txt
Unstaged changes after reset:
M       readme.txt

git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。再用git status查看一下,现在暂存区是干净的,工作区有修改:

$ 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.txt

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

还记得如何丢弃工作区的修改吗?git checkout – readme.txt

$ git checkout -- readme.txt

$ git status
On branch master
nothing to commit, working tree clean

整个世界都安静了

4.删除文件

一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm命令删了:

$ rm LICENSE.txt

这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了:

$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    LICENSE.txt

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

现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit,这样文件就从版本库中被删除了。

$ git rm LICENSE.txt
rm 'LICENSE.txt'

$ git commit -m "remove LICENSE.txt"
[master 96b0c8b] remove LICENSE.txt
 1 file changed, 1 deletion(-)
 delete mode 100644 LICENSE.txt

另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:

$ git checkout -- LICENSE.txt

5.删除文件夹及底下所有文件

git rm -r directory
git commit -m "xxxxx"
git push gitee master

6.删除文件夹下某个文件

git rm directory/file1.txt
git commit -m "xxxxx"
git push gitee master

7.重命名文件

git mv directory1/file1.txt directory2/file2.txt
git commit -m "xxxxx"
git push gitee master

git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。注意:从来没有被添加到版本库就被删除的文件,是无法恢复的!

三、远程仓库

1.创建SSH KEY

1、创建SSH Key。在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:

$ ssh-keygen -t rsa -C "youremail@example.com"

你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
2、登陆GitHub,打开“Account settings”,“SSH Keys”页面:然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容。
为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。当然,GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。

2.添加远程库

1、现在的情景是,你已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作,真是一举多得。首先,登陆GitHub,然后,在右上角找到“Create a new repo”按钮,创建一个新的仓库:目前,在GitHub上的这个PowerPoint仓库还是空的,GitHub告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库。现在,我们根据GitHub的提示,在本地的PowerPoint仓库下运行命令:

git remote add origin git@github.com:dgdqqxxx/Papers.git

添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。下一步,就可以把本地库的所有内容推送到远程库上:

$ git push -u origin master
The authenticity of host 'github.com (20.205.243.166)' can't be established.
ECDSA key fingerprint is SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,20.205.243.166' (ECDSA) to the list of known hosts.
Enumerating objects: 21, done.
Counting objects: 100% (21/21), done.
Delta compression using up to 12 threads
Compressing objects: 100% (16/16), done.
Writing objects: 100% (21/21), 1.74 KiB | 197.00 KiB/s, done.
Total 21 (delta 4), reused 0 (delta 0)
remote: Resolving deltas: 100% (4/4), done.
To github.com:dgdqqxxx/Papers.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
推送成功后,可以立刻在GitHub页面中看到远程库的内容已经和本地一模一样,从现在起,只要本地作了提交,就可以通过命令:

$ git push origin master

把本地master分支的最新修改推送至GitHub,现在,你就拥有了真正的分布式版本库!

3.删除远程库

如果添加的时候地址写错了,或者就是想删除远程库,可以用git remote rm 命令。使用前,建议先用git remote -v查看远程库信息:

$ git remote -v
origin  git@github.com:michaelliao/learn-git.git (fetch)
origin  git@github.com:michaelliao/learn-git.git (push)

然后,根据名字删除,比如删除origin:

$ git remote rm origin

此处的“删除”其实是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库本身并没有任何改动。要真正删除远程库,需要登录到GitHub,在后台页面找到删除按钮再删除

4.从远程库克隆

假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆。首先,登陆GitHub,创建一个新的仓库,名字叫gitskills;我们勾选Initialize this repository with a README,这样GitHub会自动为我们创建一个README.md文件。创建完毕后,可以看到README.md文件;现在,远程库已经准备好了,下一步是用命令git clone克隆一个本地库:

$ git clone git@github.com:michaelliao/gitskills.git
Cloning into 'gitskills'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3
Receiving objects: 100% (3/3), done.

如果有多个人协作开发,那么每个人各自从远程克隆一份就可以了。你也许还注意到,GitHub给出的地址不止一个,还可以用https://github.com/michaelliao/gitskills.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。

四、分支管理

1.创建与合并分支

首先,我们创建dev分支,然后切换到dev分支:

$ git checkout -b dev
Switched to a new branch 'dev'

git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:

$ git branch dev
$ git checkout dev
Switched to branch 'dev'

然后,用git branch命令查看当前分支:

$ git branch
* dev
  master

git branch命令会列出所有分支,当前分支前面会标一个*号。然后,我们就可以在dev分支上正常提交,比如对readme.txt做个修改,加上一行:

Creating a new branch is quick.

然后提交:

$ git commit -m "branch test"
[dev d2d553b] branch test
 1 file changed, 2 insertions(+), 1 deletion(-)

现在,dev分支的工作完成,我们就可以切换回master分支:

$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.

切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!因为那个提交是在dev分支上,而master分支此刻的提交点并没有变;现在,我们把dev分支的工作成果合并到master分支上:

$ git merge dev
Updating c7b3aa3..d2d553b
Fast-forward
 readme.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

git merge命令用于合并指定分支到当前分支。合并后,再查看readme.txt的内容,就可以看到,和dev分支的最新提交是完全一样的。注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。当然,也不是每次合并都能Fast-forward,我们后面会讲其他方式的合并。合并完成后,就可以放心地删除dev分支了:

$ git branch -d dev
Deleted branch dev (was d2d553b).

删除后,查看branch,就只剩下master分支了;因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。

$ git branch
* master

我们注意到切换分支使用git checkout ,而前面讲过的撤销修改则是git checkout – ,同一个命令,有两种作用,确实有点令人迷惑。实际上,切换分支这个动作,用switch更科学。因此,最新版本的Git提供了新的git switch命令来切换分支:创建并切换到新的dev分支,可以使用:

$ git switch -c dev

直接切换到已有的master分支,可以使用:

$ git switch master

当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。用git log --graph命令可以看到分支合并图。

$ git log --graph --pretty=oneline --abbrev-commit
*   cf810e4 (HEAD -> master) conflict fixed
|\  
| * 14096d0 (feature1) AND simple
* | 5dc6824 & simple
|/  
* b17d20e branch test
* d46f35e (origin/master) remove test.txt
* b84166e add test.txt
* 519219b git tracks changes
* e43a48b understand how stage works
* 1094adb append GPL
* e475afc add distributed
* eaadf4e wrote a readme file

2.分支管理策略

通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。创建dev分支并修改,切回master分支后合并:

$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
 readme.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。合并后,我们用git log看看分支历史。合并分支时,加上–no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

$ git log --graph --pretty=oneline --abbrev-commit
*   581b597 (HEAD -> master) merge with no-ff
|\
| * 553cdad (dev) add merge
|/
*   ffc7950 conflict fixed
|\
| * 488a661 AND simple
* | 8142019 & simple
|/
* d2d553b branch test
* c7b3aa3 (origin/master) understand stage better
* 801bb03 git tracks changes
* 9e62a11 understand how stage works
* a21669c add stage
* 2fbfd19 append GPL
* 3d33a89 add distributed
* 092abe7 wrote a readme file

3.Bug分支

Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:

$ git stash
Saved working directory and index state WIP on dev: 553cdad add merge

现在,用git status查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复bug。首先确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建临时分支:

$ 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 …”,然后提交:

$ git add readme.txt 
$ git commit -m "fix bug 101"
[issue-101 4c805e2] fix bug 101
 1 file changed, 1 insertion(+), 1 deletion(-)

修复完成后,切换到master分支,并完成合并,最后删除issue-101分支

$ 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 'recursive' strategy.
 readme.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git branch -d issue-101
Deleted branch issue-101 (was aff9962).

现在,是时候接着回到dev分支干活了!

$ git switch dev
Switched to branch 'dev'

$ git status
On branch dev
nothing to commit, working tree clean

工作区是干净的,刚才的工作现场存到哪去了?用git stash list命令看看:

$ git stash list
stash@{0}: WIP on dev: f52c633 add merge

工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;另一种方式是用git stash pop,恢复的同时把stash内容也删了:

$ git stash pop
On branch dev
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.txt

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

再用git stash list查看,就看不到任何stash内容了;你可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:

$ git stash apply stash@{0}

在master分支上修复了bug后,我们要想一想,dev分支是早期从master分支分出来的,所以,这个bug其实在当前dev分支上也存在。那怎么在dev分支上修复同样的bug?重复操作一次,提交不就行了?有木有更简单的方法?有!同样的bug,要在dev上修复,我们只需要把aff9962 fix bug 101这个提交所做的修改“复制”到dev分支。注意:我们只想复制aff9962 fix bug 101这个提交所做的修改,并不是把整个master分支merge过来。为了方便操作,Git专门提供了一个cherry-pick命令,让我们能复制一个特定的提交到当前分支:

$ git add readme.txt

$ git commit -m "git stash commit"
[dev 563ba4d] git stash commit
 1 file changed, 1 insertion(+)

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 8 commits.
  (use "git push" to publish your local commits)

$ git log --graph --pretty=oneline --abbrev-commit
*   756294c (HEAD -> master) merged bug fixed 101
|\
| * aff9962 fix bug 101
|/
*   581b597 merge with no-ff
|\
| * 553cdad (dev) add merge
|/
*   ffc7950 conflict fixed
|\
| * 488a661 AND simple
* | 8142019 & simple
|/
* d2d553b branch test
* c7b3aa3 (origin/master) understand stage better
* 801bb03 git tracks changes
* 9e62a11 understand how stage works
* a21669c add stage
* 2fbfd19 append GPL
* 3d33a89 add distributed
* 092abe7 wrote a readme file

找到fix bug 101 aff9962这个提交

$ git cherry-pick aff9962
[dev 2f246d3] fix bug 101
 Date: Wed Feb 9 20:07:02 2022 +0800
 1 file changed, 1 insertion(+), 1 deletion(-)

4.Feature分支

添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。

$ git switch -c feature-vulcan
Switched to a new branch 'feature-vulcan'

$ git add vulcan.py

$ git status
On branch feature-vulcan
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   vulcan.py

$ git commit -m "add feature vulcan"
[feature-vulcan 287773e] add feature vulcan
 1 file changed, 2 insertions(+)
 create mode 100644 vulcan.py

切回dev,准备合并:

$ git switch dev

此时又不需要这个功能了,需要删除

$ git branch -d feature-vulcan
error: The branch 'feature-vulcan' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature-vulcan'.

销毁失败。Git友情提醒,feature-vulcan分支还没有被合并,如果删除,将丢失掉修改,如果要强行删除,需要使用大写的-D参数。现在我们强行删除:

$ git branch -D feature-vulcan
Deleted branch feature-vulcan (was 287773e).

终于删除成功!

5.多人协作

要查看远程库的信息,用git remote;

$ git remote
origin

或者,用git remote -v显示更详细的信息;下面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。

$ git remote -v
origin  git@github.com:dgdqqxxx/Papers.git (fetch)
origin  git@github.com:dgdqqxxx/Papers.git (push)

1、推送分支:
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:

$ git push origin master

如果要推送其他分支,比如dev,就改成:

$ git push origin dev

总之,就是在Git中,分支完全可以在本地自己藏着玩,是否推送,视你的心情而定!

2、抓取分支:
多人协作时,大家都会往master和dev分支上推送各自的修改。
现在,模拟一个你的小伙伴,可以在另一台电脑(注意要把SSH Key添加到GitHub)或者同一台电脑的另一个目录下克隆:

$ git clone git@github.com:michaelliao/learngit.git
Cloning into 'learngit'...
remote: Counting objects: 40, done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 40 (delta 14), reused 40 (delta 14), pack-reused 0
Receiving objects: 100% (40/40), done.
Resolving deltas: 100% (14/14), done.

当你的小伙伴从远程库clone时,默认情况下,你的小伙伴只能看到本地的master分支。现在,你的小伙伴要在dev分支上开发,就必须创建远程origin的dev分支到本地,于是他用这个命令创建本地dev分支:

$ git checkout -b dev origin/dev

当你的小伙伴从远程库clone时,默认情况下,你的小伙伴只能看到本地的master分支。现在,你的小伙伴要在dev分支上开发,就必须创建远程origin的dev分支到本地,于是他用这个命令创建本地dev分支:

$ git checkout -b dev origin/dev

现在,他就可以在dev上继续修改,然后,时不时地把dev分支push到远程:

$ git add env.txt

$ git commit -m "add env"
[dev 7a5e5dd] add env
 1 file changed, 1 insertion(+)
 create mode 100644 env.txt

$ git push origin dev
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 308 bytes | 308.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
   f52c633..7a5e5dd  dev -> dev

你的小伙伴已经向origin/dev分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:

$ cat env.txt
env

$ git add env.txt

$ git commit -m "add new env"
[dev 7bd91f1] add new env
 1 file changed, 1 insertion(+)
 create mode 100644 env.txt

$ git push origin dev
To github.com:michaelliao/learngit.git
 ! [rejected]        dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送:

$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> dev

git pull也失败了,原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接:

$ git branch --set-upstream-to=origin/dev dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.

再pull:

$ git pull
Auto-merging env.txt
CONFLICT (add/add): Merge conflict in env.txt
Automatic merge failed; fix conflicts and then commit the result.

这回git pull成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再push:

$ git commit -m "fix env conflict"
[dev 57c53ab] fix env conflict

$ git push origin dev
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 621 bytes | 621.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
   7a5e5dd..57c53ab  dev -> dev

因此,多人协作的工作模式通常是这样:
首先,可以试图用git push origin 推送自己的修改;
如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
如果合并有冲突,则解决冲突,并在本地提交;
没有冲突或者解决掉冲突后,再用git push origin 推送就能成功!
如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to origin/。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
小结
查看远程库信息,使用git remote -v;
本地新建的分支如果不推送到远程,对其他人就是不可见的;
从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name;
从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。

五、Git标签

1.创建标签

在Git中打标签非常简单,首先,切换到需要打标签的分支上;然后,敲命令git tag 就可以打一个新标签:可以用命令git tag查看所有标签:

$ git tag v1.0

默认标签是打在最新提交的commit上的。有时候,如果忘了打标签,比如,现在已经是周五了,但应该在周一打的标签没有打,怎么办?方法是找到历史提交的commit id,然后打上就可以了:

$ git tag v0.9 f52c633

注意,标签不是按时间顺序列出,而是按字母排序的。可以用git show 查看标签信息:

$ git show v0.9
commit 553cdade66a0ccdf68356d6e1ce399b5e05ece13 (tag: v0.9)
Author: dgdqqxxx <2521257530@qq.com>
Date:   Wed Feb 9 19:56:05 2022 +0800

    add merge

diff --git a/readme.txt b/readme.txt
index 294d3b9..9b4f625 100644
--- a/readme.txt
+++ b/readme.txt
@@ -3,4 +3,4 @@ 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.
-
+add merge.

还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:

$ git tag -a v0.1 -m "version 0.1 released" 1094adb

用命令git show 可以看到说明文字:

$ git show v0.1
tag v0.1
Tagger: dgdqqxxx <2521257530@qq.com>
Date:   Wed Feb 9 21:35:02 2022 +0800

version 0.1 released

commit c101645f72c8294e171da1b6c73fcf897a954013 (HEAD -> master, tag: v1.0, tag: v0.1, origin/master)
Merge: 756294c 2f246d3
Author: dgdqqxxx <2521257530@qq.com>
Date:   Wed Feb 9 20:28:12 2022 +0800

    Merge branch 'dev'

2.操作标签

如果标签打错了,也可以删除:

$ git tag -d v0.1
Deleted tag 'v0.1' (was f15b0dd)

因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除。如果要推送某个标签到远程,使用命令git push origin :

$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0)
To github.com:dgdqqxxx/Papers.git
 * [new tag]         v1.0 -> v1.0

或者,一次性推送全部尚未推送到远程的本地标签:

$ git push origin --tags
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 165 bytes | 165.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To github.com:dgdqqxxx/Papers.git
 * [new tag]         v0.1 -> v0.1
 * [new tag]         v0.9 -> v0.9

如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:

$ git tag -d v0.9
Deleted tag 'v0.9' (was f52c633)

如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:

$ git push origin :refs/tags/v0.9
To github.com:michaelliao/learngit.git
 - [deleted]         v0.9

六、Gitee

1.使用Gitee

一个本地库能不能既关联GitHub,又关联Gitee呢,可以;使用多个远程库时,我们要注意,git给远程库起的默认名称是origin,如果有多个远程库,我们需要用不同的名称来标识不同的远程库。仍然以DocPaperst本地库为例,我们先删除已关联的名为origin的远程库:

git remote rm origin

然后,先关联GitHub的远程库:

$ git remote add github git@github.com:dgdqqxxx/Papers.git

注意,远程库的名称叫github,不叫origin了。
接着,再关联Gitee的远程库:

$ git remote add gitee git@gitee.com:mou_sheng/doc-papers.git

同样注意,远程库的名称叫gitee,不叫origin。
现在,我们用git remote -v查看远程库信息,可以看到两个远程库:

$ git remote -v
gitee   git@gitee.com:mou_sheng/doc-papers.git (fetch)
gitee   git@gitee.com:mou_sheng/doc-papers.git (push)
github  git@github.com:dgdqqxxx/Papers.git (fetch)
github  git@github.com:dgdqqxxx/Papers.git (push)

如果要推送到GitHub,使用命令:

$ git push github master

如果要推送到Gitee,使用命令:

$ git push gitee master

参考

廖雪峰的官方网站

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值