我的python之路【第二十一章】git的使用

GIT基本使用

版本控制工具主要实现2个功能:

版本管理

在开发中,这是刚需,必须允许可以很容易对产品的版本进行任意回滚,版本控制工具实现这个功能的原理简单来讲,就是你每修改一次代码,它就帮你做一次快照

协作开发

一个复杂点的软件,往往不是一个开发人员可以搞定的,公司为加快产品开发速度,会招聘一堆跟你一样的开发人员开发这个产品,拿微信来举例,现在假设3个人一起开发微信,A开发联系人功能,B开发发文字、图片、语音通讯功能,C开发视频通话功能, B和C的功能都是要基于通讯录的,你说简单,直接把A开发的代码copy过来,在它的基础上开发就好了,可以,但是你在他的代码基础上开发了2周后,这期间A没闲着,对通讯录代码作了更新,此时怎么办?你和他的代码不一致了,此时我们知道,你肯定要再把A的新代码拿过来替换掉你手上的旧通讯录功能代码, 现在人少,3个人之间沟通很简单,但想想,如果团队变成30个人呢?来回这样copy代码,很快就乱了, 所以此时亟需一个工具,能确保一直存储最新的代码库,所有人的代码应该和最新的代码库保持一致

2.安装Git

1.在Linux下安装Git

yum install -y git
sudo apt-get install git 

3.版本库创建

什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
所以,创建一个版本库非常简单,首先,选择一个合适的地方,创建一个空目录:

1. mkdir githome
2. cd githome
3. git init 
Initialized empty Git repository in C:/Users/user/githome/.git/

这样一个git仓库就创建好了,并且会告诉你这是一个初始化了一个空的Git仓库。这里会发现多出来一个.git的隐藏文件

需要注意:所有的版本控制只能跟踪文本文件的改动。视频和图片等二进制文件我们无法捕捉到文件内部的变化,只能追踪到文件大小和状态的变化。

git区域划分

1. 工作区(working directory)
2. 暂缓区(stage index)
3. 历史记录区(history)

git工作区域 文件的4种状态

分别是未修改unmodified、修改modified、暂存staged。
对于没有加入git控制的文件,可以视为第四种状态未跟踪untracked
新创建的文件-Untracked files  新创建的文件在工作区域

在使用Git之前我们设置一下用户和邮箱

git config --global user.name liuhao
git config --global user.name xxx@qq.com

我们来进行一次完整的提交

vim readme.txt
first commit -it's happy

在githome下创建文件,或者在子目录下创建文件,因为githome是一个Git仓库,放到其他位置Git就无法找到文件了。

查看当前工作区域内为提交的文件-

git status

第一步,用命令git add 告诉Git,把文件添加到暂存区

git add readme

第二步,用命令git commit 告诉git,将文件提交到仓库:

#git commit -m '提交描述'
git commit -m 'first commit'

git add 也可以一次提交多个文件

git add file1 file2
提交当前目录下所有文件
git add .  
git commit -m '描述'
git commit  #提交后编写详细的表述内容

4.代码回滚

4.1 代码修改并提交

vim readme

first commit -it's happy
2 commit

vim 2.conf
2222222222222

运行git status 查看状态

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

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        2.conf

查看工作区域和本地仓库中的文件进行对比

git diff file

 $ git diff readme
diff --git a/readme b/readme
index 44dee0d..bed7ea9 100644
--- a/readme
+++ b/readme
@@ -1 +1,2 @@
 first commit -it's happy
+2 commit
warning: LF will be replaced by CRLF in readme.
The file will have its original line endings in your working directory.

执行git add 和 git commit 提交代码

git add .
git commit -m '2提交'

提交完成后,我们再次执行git status查看仓库的当前状态

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

4.2 代码回滚

我们这样,不断的对文件进行修改,然后不断提交到版本库里。相当于在这个位置做了一个快照。这个快照在git中称为commit。一旦你把文件改错了,或者误删了文件,还可以从一个commit中恢复回来。继续工作。而不至于将工作成果全部丢失

回顾一下,我们的readme 有几个版本被提交到Git仓库了。

版本1 :

first commit -it's happy

版本2:

vim readme

first commit -it's happy
2 commit

vim 2.conf
2222222222222

版本3:

vim readme
first commit -it's happy
2 commit
3 commit

查看提交的历史版本: git log

#包含了版本ID,提交的描述
$ git log
commit 37824a601fab02932f576098c72e50d9359019f5
Author: xxx@qq.com <354165044@qq.com>
Date:   Mon Jun 19 17:52:21 2017 +0800

    3次提交

commit 47a95dc06ed1bfc0bb9150515b5a130e78970b5a
Author: xxx@qq.com <354165044@qq.com>
Date:   Mon Jun 19 17:51:11 2017 +0800

    2提交

commit 5d13bf41eee809302d4e123e4960c46effab88c4
Author: xxx@qq.com <354165044@qq.com>
Date:   Mon Jun 19 17:50:03 2017 +0800

    1commit

git log 命令显示从最近到最远的提交日志我们可以看到3次。
如果嫌输出的信息太多,可以加上--pretty=oneline参数

$ git log --pretty=oneline
37824a601fab02932f576098c72e50d9359019f5 3次提交
47a95dc06ed1bfc0bb9150515b5a130e78970b5a 2提交
5d13bf41eee809302d4e123e4960c46effab88c4 1commit

当一个项目提交的次数非常多的时候 加上'-2'显示最后两次提交

$ git log --pretty=oneline -2
37824a601fab02932f576098c72e50d9359019f5 3次提交
47a95dc06ed1bfc0bb9150515b5a130e78970b5a 2提交

我们看到的47a95dc...70b5a是commit id(版本号),是一个sha1计算出来的数字,用16进制表示

开始进行回滚操作

首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交47a95dc06ed1bfc0bb9150515b5a130e78970b5a(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD,上上一个版本就是HEAD,当然往上100个版本写100个比较容易数不过来,所以写成HEAD~100

现在我们把当前版本回退到上一个版本:命令 git reset --hard

$ git reset --hard HEAD^
HEAD is now at 47a95dc 2提交

查看一下readme文件,确实回到了第二次的版本

$ ll
total 2
-rw-r--r-- 1 user 197121 10 六月 19 17:50 2.conf
-rw-r--r-- 1 user 197121 36 六月 19 18:01 readme
$ cat readme
first commit -it's happy
2 commit

查看一下版本:发现没有了第三次提交的commit id(这个问题下文解决)

$ git log --pretty=oneline
47a95dc06ed1bfc0bb9150515b5a130e78970b5a 2提交
5d13bf41eee809302d4e123e4960c46effab88c4 1commit

我们先尝试回滚到指定版本

git reset --hard 5d13bf

版本号不需要写全,前6,7位就可以,git会自动查找.

上文提到,我们的git log中已经无法查询到第3次和第2次的提交版本了
如何解决呢?

引入下面这个git reflog 查看所有版本提交和回退操作

$ git reflog
5d13bf4 HEAD@{0}: reset: moving to 5d13bf
47a95dc HEAD@{1}: reset: moving to HEAD^
37824a6 HEAD@{2}: commit: 3次提交
47a95dc HEAD@{3}: commit: 2提交
5d13bf4 HEAD@{4}: commit (initial): 1commit

工作区和暂存区

工作区(Working Directory)

就是你在电脑里能看到的目录,比如我的git_trainning文件夹就是一个工作区:

$ ls githome/
2.conf  readme

版本库(Repository)

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

工作区-版本库(stage部分 和 master部分)

git add 命令实际上就是将所有修改放到暂存区(Stage),然后,执行git commit 将暂存区的所有修改提交至分支

情况一:代码在工作区,未提交
1.你在readme中加入一个一行:

first commit -it's happy
2 commit
3 commit
测试 解决
  1. 经过很长时间的代码编写,打算提交的时候,想去除这条记录'测试 解决'

你可以通过git status查看一下 显示文件状态是modified

$ 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
no changes added to commit (use "git add" and/or "git commit -a")

Git 可以丢弃工作区的修改: git checkout -- file

git checkout -- readme

命令git checkout -- readme.md意思就是,把readme.md文件在工作区的修改全部撤销,这里有两种情况:

一种是readme.md自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;

一种是readme.md已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commit或git add时的状态。

git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令。

情况二:将代码提交到暂存区,还未提交

如果你将写错的代码git add 添加到了缓存区,还没有提交。

命令 git reset HEAD file 可以把缓存区的修改撤销掉,重新放回至工作区:

git reset HEAD readme

git reset 既可以回退版本,也可以把缓存区修改回退至工作区。当我们用HEAD时,表示最新的版本

删除操作

1.git中,先创建一个新文件test.txt ,并且提交:

$ vim test.txt
delete
$ git add .
$ git commit -m 'delete test'
[master 9037195] delete test
 1 file changed, 1 insertion(+)
 create mode 100644 test.txt

2.我们正常的删除test.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:    test.txt

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

现在你有两种选择,
1.确定要从版本库中删除文件,命令 git rm,并且git commit:

$ git rm test.txt
rm 'test.txt'

user@user-PC MINGW64 ~/githome (master)
$ git commit -m 'remove test.txt'
[master 6f59b99] remove test.txt
 1 file changed, 1 deletion(-)
 delete mode 100644 test.txt

此时文件就从版本库删除了。

2.属于误操作,因为版本库中还存在,我们可以将误删的文件恢复到最新版本:

git checkout -- test.txt

git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。 

Git高级使用部分

远程仓库

连接远程仓库有两种方式:1.通过ssh-key秘钥验证 2.通过用户名密码验证

1、通过ssh-key秘钥验证

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

 ssh-keygen -t rsa -C "xxx@qq.com"
#写入自己的邮箱地址。

创建完成后,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。

友情提示: github是开源的,所以你上传的代码别人都是可以看到的。注意将自己的代码中敏感信息去除。

新创建一个远程仓库

…or create a new repository on the command line
#创建一个新的本地仓库,并推送到新创建的远程仓库: 下面是命令
echo "# new_git_repository" >> README.md
  git init
  git add README.md
  git commit -m "first commit"
  git remote add origin git@github.com:NoSongmaster/new_git_repository.git
  git push -u origin master
  
…or push an existing repository from the command line
#将现有的本地仓库,推送到远程仓库 : 下面是命令
  git remote add origin git@github.com:NoSongmaster/new_git_repository.git
  git push -u origin master

我们根据提示进行向远程仓库提交:

#添加远程仓库
$ git remote add origin git@github.com:NoSongmaster/new_git_repository.git

user@user-PC MINGW64 ~/githome (master)
#向远端提交
$ git push -u origin master
Counting objects: 14, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (14/14), 1.05 KiB | 0 bytes/s, done.
Total 14 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), done.
To github.com:NoSongmaster/new_git_repository.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

user@user-PC MINGW64 ~/githome (master)
#查看git提交状态
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean

远程仓库添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。

把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。

此时在github上刷新一下,就可以看到从本地推送上来的文件了。

此时,只要在本地完成提交,再向远程仓库推送只需要执行

git push origin master

进行一次完整的向远程仓库推送

$ vim test_repo
$ cat test_repo
就是测试repo
$ git add .
warning: LF will be replaced by CRLF in test_repo.
The file will have its original line endings in your working directory.
$ git commit -m 'test repo'
[master d2c31fd] test repo
 1 file changed, 1 insertion(+)
 create mode 100644 test_repo
$ git push origin master
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 312 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:NoSongmaster/new_git_repository.git
   6f59b99..d2c31fd  master -> master

在工作中一般,会给你一个原有的远程仓库,你需要先将公司的代码克隆到本地库

直接在装有git的窗口执行:git clone "URL"
$ git clone git@192.168.10.4:devops/Free.git
Cloning into 'Free'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.

或者你在工作中,你有自己的本地仓库,想将远程仓库的代码拉取到本地仓库
关联远程库
git remote add origin git@github.com:NoSongmaster/new_git_repository.git
将远程仓库的代码拉取到本地
git pull origin master

分支管理

1.创建分支

#创建一个分支dev 并切换至dev分支上
git checkout -b dev

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

git branch dev
git checkout dev

查看当前分支 git branch
$ git branch
* dev
master

git brach 会列出所有的分支,当前分支前面会标一个*号

我们在dev分支上正常提交,比如对readme.txt做一个修改。

vim readme
first commit -it's happy
2 commit
3 commit
test branch

提交

$ git add .
user@user-PC MINGW64 ~/githome (dev)
$ git commit  -m 'branch dev'
[dev a2e6da7] branch dev
 1 file changed, 1 insertion(+)

此时在dev分支上的工作完成了,我们切回到master分支上。

$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
$ cat readme
first commit -it's happy
2 commit
3 commit

发现,readme中,在dev分支上添加的内容不见了,因为那个提交时在dev分支上的,而在master分支此刻的提交点并没有变:

我们需要将dev分支的工作成果合并到master分支上。

$ git merge dev
Updating d2c31fd..a2e6da7
Fast-forward
 readme | 1 +
 1 file changed, 1 insertion(+)

合并分支的命令: git merge dev (因为此时在master上)

git merge 命令用于合并指定分支到当前分支,合并后,再查看readme内容,就可以看到了。

注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。

当然,也不是每次合并都能Fast-forward,我们后面会讲其他方式的合并。

合并完成后,就可以放心的删除dev分支了:

#删除分支命令
$ git branch -d dev
Deleted branch dev (was a2e6da7).
#删除后查看分支情况
$ git branch
* master

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

解决冲突问题待续

参考博客:

http://www.cnblogs.com/alex3714/articles/5930846.html

posted @ 2017-06-23 10:55  saynobody  阅读(222)  评论(0编辑  收藏  举报