Git

安装

直接下载安装即可

初始工作

初始化仓库:
可以将空文件将当成仓库,也可以将有文件的文件夹当成仓库,然后进行初始化
git init
初始化之后会自动新增一个.git的目录,这个目录是 Git 来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把 Git 仓库给破坏了。
添加文件到暂存区:
新建文件,或者把已经建好的文件放到仓库文件夹目录下(子目录下也行),然后运行添加命令
git add readme.txt
可以将多个文件添加到暂存区,然后使用git commit一次性提交到版本库
提交文件到版本库:
git commit -m "wrote a readme file" # -m后面输入的是本次提交的说明

本地版本控制

git status # 查看当前状态(有没有文件需要添加到暂存区,有没有文件需要提交到版本库) git status readme.txt # 查看当前文件的状态 git diff readme.txt # 查看文件修改内容 git diff HEAD -- readme.txt # 查看工作区和版本库里面最新版本的区别 git log # 查看历史版本,显示详细信息 git log --pretty=oneline # 只显示版本号和提交说明 # 在版本号后面有 (HEAD -> master) 的表示版本库当前最新版本 # 版本回退 git reset --hard HEAD^ # 回退到当前版本的上一个版本 # 回退一个版本后悔了?又想回到最新版本? git reset --hard 1094a # --hard后面是版本号,记住后悔的那个版本,你就能回去 # 要是记不住最新版本的版本号咋办? git reflog # 记录你的每次操作命令以及版本号 # 撤销修改 git checkout -- readme.txt # 把readme.txt文件在工作区的修改全部撤销 # 一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态; # 一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。 # git checkout -- file 命令中的--很重要,没有--,就变成了 “切换到另一个分支” 的命令 git reset HEAD readme.txt # 把暂存区的修改撤销掉(unstage),重新放回工作区 # 删除文件 # 1.确实想要删除文件 # 在文件夹下把文件删除,然后用 git rm 命令删除工作区的文件,再提交到版本库 rm test.txt # 这一步可以省略,直接用git rm命令 git rm test.txt # 这里效果和git add一样 git commit -m "remove test.txt" # 2.误删文件 git checkout -- test.txt # git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以 “一键还原”。

远程仓库

1、创建 SSH Key

在本地电脑操作
ssh-keygen -t rsa -C "anjhon@163.com"
如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是 SSH Key 的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
ssh -T git@github.com # 验证是否配置成功,成功则会出现以下提示信息 ## “Hi lover! You've successfully authenticated, but GitHub does not provide shell access.”

2、设置GitHub

  • 将id_rsa.pub文件中的内容粘贴到github,设置中的shh中
  • 创建一个GitHub仓库

3、关联远程仓库

git remote add origin git@github.com:michaelliao/learngit.git # 关联仓库 git remote -v # 查看远程库信息 git remote rm origin # 解除了本地和远程的绑定关系

4、远程仓库操作

推送
git push -u origin master
由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git 不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
克隆
git clone git@github.com:michaelliao/gitskills.git

分支管理

1、分支原理

master分支是一条线,Git 用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点
notion imagenotion image
当我们创建新的分支,例如dev时,Git 新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上
notion imagenotion image
从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变
notion imagenotion image
合并的时候就是直接把master指向dev的当前提交,就完成了合并
notion imagenotion image
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支
notion imagenotion image

2、相关指令

git branch dev # 创建分支 git checkout dev # 切换分支 git checkout -b dev # 上面量个命令的合并:创建并切换分支 git switch feature1 # 切换分支 git switch -c feature1 # 创建并切换分支(与上面的命令功能相似) git branch # 会列出所有分支,当前分支前面会标一个*号 git merge dev # 合并指定分支到当前分支 git branch -d dev # 删除分支 # 查看分支合并图 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
因为创建、合并和删除分支非常快,所以 Git 鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。

3、分支管理策略

通常,合并分支时,如果可能,Git 会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。如果要强制禁用Fast forward模式,Git 就会在 merge 时生成一个新的 commit,这样,从分支历史上就可以看出分支信息。
-no-ff参数,表示禁用Fast forward;因为本次合并要创建一个新的 commit,所以加上-m参数,把 commit 描述写进去。
git merge --no-ff -m "merge with no-ff" dev
这样即使删除了分支,也能看到分支提交和修改的历史
在实际开发中,我们应该按照几个基本原则进行分支管理:首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如 1.0 版本发布时,再把dev分支合并到master上,在master分支发布 1.0 版本;你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。所以,团队合作的分支看起来就像这样:
notion imagenotion image

4、Bug分支

当你接到一个修复一个代号 101 的 bug 的任务时,很自然地,你想创建一个分支issue-101来修复它,但是,等等,当前正在dev上进行的工作还没有提交而是工作只进行到一半,还没法提交,预计完成还需 1 天时间。但是,必须在两个小时内修复该 bug,怎么办?幸好,Git 还提供了一个stash功能,可以把当前工作现场 “储藏” 起来,等以后恢复现场后继续工作:
git stash # 将当前“工作现场”储藏起来 Saved working directory and index state WIP on dev: f52c633 add merge。 git stash list # 查看储藏起来的“工作现场” git stash apply # 恢复工作现场,同时在“储藏区”还会保留这个工作现场, git stash pop # 恢复工作现场,同时删除“储藏区”的这个工作现场 git cherry-pick 4c805e2 # 复制一个特定的提交(用版本id区分)到当前分支对应的位置,进行提交
# Bug修复过程 $ git checkout master # 要修复master上的bug,先切回到master $ git checkout -b issue-101 # 创建临时bug分支,并切换 $ git add readme.txt # 修复后添加文件 $ git commit -m "fix bug 101" # 提交 $ git switch master # 再次切回master主分支 $ git merge --no-ff -m "merged bug fix 101" issue-101 # 合并bug分支和主分支 # 丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。 $ git branch -D feature-vulcan

5、多人协作

git remote # 查看远程库的分支信息 git remote -v # 显示更详细的信息(显示了可以抓取和推送的origin的地址) origin git@github.com:michaelliao/learngit.git (fetch) origin git@github.com:michaelliao/learngit.git (push) $ git push origin master # 推送master分支 $ git push origin dev # 推送dev分支
当clone远程库到本地时,默认只能拉取到master主分支,如果想要在其他分支上开发,比如在dev分支上开发,则要单独创建远程origin的dev分支到本地
$ git checkout -b dev origin/dev # 创建远程origin的dev分支到本地
多人提交冲突:
解决办法也很简单,Git 已经提示我们,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送
# pull失败(提示no tracking information,说明说明本地分支和远程分支的链接关系没有创建) $ 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 push origin <branch-name>
  • 推送自己的修改;如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
  • 如果合并有冲突,则解决冲突,并在本地提交;
  • 没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功!

6、标签管理

在 Git 中打标签非常简单,首先,切换到需要打标签的分支上:
$ git branch * dev master $ git checkout master Switched to branch 'master'
然后,敲命令git tag <name>就可以打一个新标签:
$ git tag v1.0 # 打标 $ git tag # 查看标签 v1.0 $ git show v1.0 # 查看标签信息 $ git tag -d v0.1 # 删除标签 $ git push origin v1.0 # 推送某个标签到远程 $ git push origin --tags # 一次性推送全部尚未推送到远程的本地标签 如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除 $ git tag -d v0.9 $ git push origin :refs/tags/v0.9
默认标签是打在最新提交的 commit 上的。有时候,如果忘了打标签,比如,现在已经是周五了,但应该在周一打的标签没有打,怎么办?方法是找到历史提交的 commit id,然后打上就可以了:
$ git tag v0.9 f52c633
还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:
$ git tag -a v0.1 -m "version 0.1 released" 1094adb
对于本文内容有任何疑问, 可与我联系.