Git教程

一、 创建版本库

初始化一个Git仓库,使用git init命令。
添加文件到Git仓库,分两步:
使用命令git add <file>,注意,可反复多次使用,添加多个文件;
使用命令git commit -m <message>,完成。

二、 时光机穿梭

  • 要随时掌握工作区的状态,使用git status命令。
  • 如果git status告诉你有文件被修改过,用git diff可以查看修改内容。

2.1 版本回退

  • HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
  • 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。git log --graph
  • 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。

2.2 工作区和暂存区

在这里插入图片描述

2.3 管理修改

Git会跟踪修改,每次修改,如果不用git add到暂存区,那就不会加入到commit中。
e.g.
第一次修改 -> git add -> 第二次修改 -> git add -> git commit

2.4 撤销修改

场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>,就回到了场景1,第二步按场景1操作。
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。

2.5 删除文件

当rm删除一个文件时,有两个选择:
一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit

$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master d46f35e] remove test.txt
 1 file changed, 1 deletion(-)
 delete mode 100644 test.txt

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

$ git checkout -- test.txt

三、远程仓库

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

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

第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面:
然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容,点“Add Key”,你就应该看到已经添加的Key。
为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
当然,GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。

3.1 添加远程库

  • 要关联一个远程库,使用命令
    git remote add origin git@server-name:path/repo-name.git;
    关联一个远程库时必须给远程库指定一个名字,origin是默认习惯命名;
  • 关联后,使用命令git push -u origin master第一次推送master分支的所有内容;(现在似乎默认是main分支了git push -u origin main
  • 此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;
  • 分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作,而SVN在没有联网的时候是拒绝干活的!当有网络的时候,再把本地提交推送一下就完成了同步,真是太方便了!

3.2 从远程库克隆

要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。
Git支持多种协议,包括https,但ssh协议速度最快。

四、分支管理

4.1 创建与合并分支

Git鼓励大量使用分支:

  • 查看分支:git branch
  • 创建分支:git branch <name>
  • 切换分支:git checkout <name>或者git switch <name>
  • 创建+切换分支:git checkout -b <name>或者git switch -c <name>
  • 合并某分支到当前分支:git merge <name>
  • 删除分支:git branch -d <name>

4.2 解决冲突

当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。
e.g.
git merge <name>或者git status都可以告诉我们冲突的文件,vi打开文件后可以看到的冲突信息:Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容。我们修改文件后保存,再提交:

$ git add readme.txt 
$ git commit -m "conflict fixed"
[master cf810e4] conflict fixed

用带参数的git log也可以看到分支的合并情况:

$ git log --graph --pretty=oneline --abbrev-commit

最后,删除feature1分支:

$ git branch -d feature1
Deleted branch feature1 (was 14096d0).

git log --graph命令可以看到分支合并图。

4.3 分支管理策略

Git分支十分强大,在团队开发中应该充分应用。
合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。
e.g.
准备合并dev分支,请注意–no-ff参数,表示禁用Fast forward:

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

4.4 Bug分支

  • 修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
    e.g.stash后才能checkout 切换
$ git status
$ git stash
$ git checkout master 
$ git checkout -b issue-101
修复完成后,切换到master分支
$ git switch master
$ git merge --no-ff -m "merged bug fix 101" issue-101
最后删除issue-101分支
$ git branch -d issue-101
接着回到dev分支干活
$ git switch dev
$ git stash pop 恢复的同时把stash内容也删了
$ git stash list 此时看不到任何stash内容了
  • 当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场;
  • 在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick <commit>命令,把bug提交的修改“复制”到当前分支,避免重复劳动。

4.5 Feature分支

开发一个新feature,最好新建一个分支;
如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。

4.6 多人协作

多人协作的工作模式通常是这样:

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

4.7 Rebase

e.g.
rebase操作前后,最终的提交内容是一致的,但是,我们本地的commit修改内容已经变化了,它们的修改不再基于d1be385 init hello,而是基于f005ed4 (origin/master) set exit=1(远端他人更新的版本),但最后的提交7e61ed4内容是一致的。

  • rebase操作可以把本地未push的分叉提交历史整理成直线;远程分支的提交历史也是一条直线。
  • rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。

五、标签管理

tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。

5.1 创建标签

  • 命令git tag <tagname>用于新建一个标签,默认为HEAD,也可以指定一个commit id;
  • 命令git tag -a <tagname> -m "blablabla..."可以指定标签信息;
  • 命令git tag可以查看所有标签。 按照字母排序而非时间
  • git show <tagname>查看标签信息

5.2 操作标签

  • 命令git push origin <tagname>可以推送一个本地标签;
  • 命令git push origin --tags可以推送全部未推送过的本地标签;
  • 命令git tag -d <tagname>可以删除一个本地标签;
  • 命令git push origin :refs/tags/<tagname>可以删除一个远程标签。

六、使用GitHub

  • 在GitHub上,可以任意Fork开源仓库;
  • 自己拥有Fork后的仓库的读写权限;
  • 可以推送pull request给官方仓库来贡献代码。

协作简易版本:

git clone repo_url
git checkout branch
...
git checkout -b feat-xxx
git status/git diff查看状态
git add .
git commit -m "xxx"
git push origin feat-xxx
在容器云的测试环境中,对该分支进行部署,测试,看性能效果
OK后,远程仓库中申请merge-request,合并到线上环境的代码库中,
最后容器云部署线上环境的代码库到线上环境中。
更新本地当前代码
git pull

git diff 命令可以用来查看工作区中未添加到暂存区的更改与本地版本库中的对比。
当你在工作区中修改了文件,但还没有将这些更改添加到暂存区时,可以使用 git diff 命令来查看这些更改。

git diff 命令会显示工作区中未暂存的更改与本地版本库中的对比。
如果你想要查看已暂存的更改,可以使用 git diff --cached 命令,或者简写为 git diff --staged。
这将显示已添加到暂存区但还未提交的更改与本地版本库中的对比。

目前经过测试发现,没git add之前,git diff只能看到修改的Java文件,新建Java文件看不到。git status能看到新建文件所在的包,但是是untracked。这是因为已有文件在本地仓库,可以通过工作区修改与本地仓库做一次对比,而新建文件不在本地仓库中,无法对比。
git add之后(ps:文件变绿),git diff就没内容了,估计diff是比较工作区未add的修改和本地仓库的区别。此时git status会显示新建的Java文件和修改的Java文件

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐