Git操作总结

161 阅读9分钟

什么是git?

Git是Linux花了两周时间用C编写的一个分布式版本控制系统。分布式版本控制系统根本没有”中央服务器“,每个人电脑都有一个完整的版本库。在实际使用中,分布式版本控制系统通常也有一台充当”中央服务器“的电脑,但这个服务器的作用仅仅是用来方便”交换“大家的修改。

创建版本库

注!本地仓库和远程仓库是两回事!

进入你想要管理的目录,使用git init命令把这个目录变成Git可以管理的仓库:

git  init

此时当前目录下多了一个.git的目录(默认隐藏,使用ls -ah就可以看见),这个目录是Git来跟踪管理版本库的。

注:所有的版本控制系统,其实只能跟踪文本文件的改动。像图片、视频这些二进制文件是没有办法跟踪文件的变化的,只能把二进制文件每次改动串起来,也就是只知道图片从100kb改成了120kb,但具体改动了啥是不知道的。

工作区和暂存区

.git的版本库存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git自动为我们创建的第一个分支master,以及指向master的一个指针叫HEAD。

0.jpeg

而把一个文件放入到Git仓库需要2步,其中add可以反复使用

# add实际上就是把文件修改添加到暂存区
git  add . (不要忘记点.)
# commit实际上就是把暂存区的所有内容提交到当前分支;每次修改如果不加到暂存区,就不会加入到commit中
git  commit -m '注释信息'

注:Git命令必须在git仓库目录内执行(除git init);添加某个文件时,该文件必须在当前目录下。

管理修改

我们都知道,Git跟踪并管理的是修改,而非文件。那怎么撤销修改呢? 先用git status查看一下当前状态

(base) liuyandeMacBook-Air:pingback_service liuyan$ 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 --file可以丢弃工作区的修改

git checkout -- readme.txt

这里有2种情况:

  1. 是文件修改后还没有被放到暂存区,现在撤销修改就回到和版本库一模一样的情况。
  2. 文件已经添加到暂存区,又做了修改,现在撤销就是回到添加到暂存区后的状态。 总之,就是让这个文件回到最近一次git commit或git add时的状态。

那如果文件已经add到暂存区的话

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

	modified:   readme.txt

可以使用命令git reset HEAD ...把暂存区的修改撤销掉,重新放回工作区。

删除文件

在Git中,删除也是一个修改操作。直接删除文件后,工作区和版本库就不一样了。 现在你有两个选择,一是确实从版本库中删除该文件

$ 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

二是删错了,那版本库里还有,就可以用checkout还原。

注意:从来没有被添加到版本库就被删除的文件,是无法恢复的!

版本回退(丢弃工作区的修改)

使用git log查看操作历史(从最近到最远)

(base) liuyandeMacBook-Air:pingback_service liuyan$ git log --pretty=oneline
3730a8257c23b741b7c5db75f216cffc3bdd116e (HEAD -> Ly-adsdk, origin/Ly-adsdk) fix AndroidID
c9403f87bbcd713740f46db3c1582a77492ae8fc fix AndroidID
3397f12328000f7d984ad5529ad413e84d51c76d end-default-remove
a30bb4234c358e552e3ba0c3a8ff709d0d573e90 Merge branch 'master' into 'Ly-adsdk'

打头一大串的id就是commit id。在Git中,HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。

那回退到一个版本可以使用git reset命令

(base) liuyandeMacBook-Air:pingback_service liuyan$ git reset --hard HEAD^

也可以使用commit id回到未来的某个版本

(base) liuyandeMacBook-Air:pingback_service liuyan$ git reset --hard 3730a(commit id 不需要全部能找到即可)

Git中使用git reflog记录你的每一次命令

(base) liuyandeMacBook-Air:pingback_service liuyan$ git reflog
3730a82 (HEAD -> Ly-adsdk, origin/Ly-adsdk) HEAD@{0}: commit: fix AndroidID
c9403f8 HEAD@{1}: commit: fix AndroidID
3397f12 HEAD@{2}: commit: end-default-remove
a30bb42 HEAD@{3}: checkout: moving from master to Ly-adsdk

远程仓库

添加远程库

现有本地仓库,后有远程库,如何关联远程库。远程仓库工程已经创建完成后,切换本地计算机工程目录,执行如下命令:

#第一步,关联远程库
git  remote add origin git@XXX.git (gitLab刚刚创建的工程地址)

# 第一次把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程
git  push -u origin master

后续只要本地做了提交,都可以通过git push origin master把本地master分支的最新修改推送到Gitlab。

修改远程库地址并提交本地改动

已经关联了远程库但是远程库换了地址,此时本地还有改动。如何把本地的更新提交到新的远程仓库工,切换本地计算机工程目录,执行如下命令:

#第一步,关联新的远程库
git  remote set-url origin git@XXX.git (gitLab新的工程地址)

# 提交改动后推送到新的远程库
git  add .
git  commit -m 'xxx'
git  push origin master(要提交的分支名)

后续只要本地做了提交,都可以通过git push origin master把本地master分支的最新修改推送到Gitlab。

远程库克隆

cd进入想要本地保存项目的路径,执行如下命令:

git clone git@code.sohuno.com:XXX

如果没有配置过本地仓库,需要先配置再clone

 git config --global user.name "Your Name"
 
 git config --global user.email "email@example.com"

为了避免每次都需要输入密码,将使用ssh登录,ssh应该与本机信息绑定。

删除远程库

先用git remote -v查看远程库信息

(base) liuyandeMacBook-Air:pingback_service liuyan$ git remote -v

origin git@code.sohuno.com:sohu-test/pingback_service.git (fetch)

origin git@code.sohuno.com:sohu-test/pingback_service.git (push)

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

分支管理

Git创建分支dev就是新建一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!在dev分支进行修改和提交都是针对dev分支的,与master无关。

# 创建dev分支并切换到该分支
git checkout -b dev/git switch -c dev 

# 查看当前分支
git branch -r(查看远程分支)/ -a(查看所有分支)

# 切换回master
git checkout master/git switch master

# 把dev分支merge到master分支;默认Fast forward模式,这种模式,删除分支后会丢掉分支信息
git merge dev

#使用--no-ff
git merge --no-ff -m "merge with no-ff" dev

# 查看分支合并情况
git log --graph --pretty=oneline --abbrev-commit

# 删除dev分支
git branch -d dev

merge时可能存在冲突,需要解决冲突后再合并

bug分支管理

修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;

当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场;

在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick 命令,把bug提交的修改“复制”到当前分支,避免重复劳动。

feature分支管理

开发一个新feature,最好新建一个分支;

如果要丢弃一个没有被合并过的分支,可以通过git branch -D 强行删除。

多人协作

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

  • 首先,可以试图用git push origin 推送自己的修改;

  • 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;

  • 如果合并有冲突,则解决冲突,并在本地提交;

  • 没有冲突或者解决掉冲突后,再用git push origin 推送就能成功!

  • 如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to origin/。

#查看远程库信息;本地新建的分支如果不推送到远程,对其他人就是不可见的;
git remote -v

#从本地推送分支;如果推送失败,先用git pull抓取远程的新提交
git push origin branch-name

#在本地创建和远程分支对应的分支;本地和远程分支的名称最好一致
git checkout -b branch-name origin/branch-name

#建立本地分支和远程分支的关联;从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。
git branch --set-upstream branch-name origin/branch-name;

这就是多人协作的工作模式,一旦熟悉了,就非常简单。

标签管理

#新建一个标签,默认为HEAD,也可以指定一个commit id
git tag <tagname>

#可以指定标签信息
git tag -a <tagname> -m "blablabla..."

#查看所有标签
git tag

#推送一个本地标签
git push origin <tagname>

#推送全部未推送过的本地标签
git push origin --tags

#删除一个本地标签
git tag -d <tagname>

#删除远程标签(如果一个标签已经推送到远程,要删除远程标签,先从本地删除,然后从远程删除)
git push origin :refs/tags/<tagname>

注意:标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。

忽略特殊文件

有些时候,你必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件啦,等等,每次git status都会显示Untracked files ...,有强迫症的童鞋心里肯定不爽。

好在Git考虑到了大家的感受,这个问题解决起来也很简单,在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。

不需要从头写.gitignore文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:github.com/github/giti…

忽略文件的原则是:

忽略操作系统自动生成的文件,比如缩略图等; 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件; 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

举个例子:

假设你在Windows下进行Python开发,Windows会自动在有图片的目录下生成隐藏的缩略图文件,如果有自定义目录,目录下就会有Desktop.ini文件,因此你需要忽略Windows自动生成的垃圾文件:

# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini

最后一步就是把.gitignore也提交到Git