Version Control System
Why we need version control system
Collaboration
- before:独立任务 working in isolation
工作中可能会共享文件夹,并可能对同一文件处理,但是却没有记录,当最后要将所有的文件merge在一起时,就可能会出现冲突,每个人都不知道别人做了怎样的修改。
- after: 合并任务combined tasks
共享同一个project,每个人对项目的更新记录都会在系统上显示,所有记录一目了然。
Storing Versions
- 更新了版本可以只存储更新过的那部分内容,节省存储空间
- 每个 version 都可被合理的命名
- 更新内容可以被自动的记录下来,不需要人为写更新文档
Backup
- 如果中央服务器崩溃,备份会存在与每个本地服务器当中
每个开发者每天早晨会先fetch all the files from the central server, and after the day working, the may upload the files back to central server. 所以说,每次merge之前,都必须要先fetch一下服务器中的文档,保证是最新的文档之后,再进行push
So every local server may hava a copy of the whole project, so a backup is always available in your loacal servers.
Analyze
Version Control Tools
- git mercurial
- SVN CVS
不提供本地备份的版本控制软件
所以,Git一直都是受欢迎的版本控制软件,SO why not?
Git & GitHub
通过右边结构层图,可推知,Github相当于是一个central repository(sever)。git 相当于是一个可以生成local repository的工具
分布式版本控制工具比集中式版本控制工具的优点
- backup
当sever崩溃时,分布式VCS tools可以提供 backup,集中式不可以。
- speed
不需要实时联网,只需要在你开始工作的时候fetch 到local repository一次,结束之后push回remote repository即可。
问题
- 如果在此中间,远程服务器中的代码有了改动。
答:所以你需要每次push 之前,可以先fetch一下,看一下有了哪些改变,是否对我今天白天的工作产生了影响。确定无误后再merge及push
- 能否自动push代码?
答:分布式版本控制工具的核心在于,当你每一次非常确认你的代码工作良好,确认无误后再手动推送到服务器。但如果你自动推送到云端的话,别人也许会使用你自动推送的未完成或者错误的代码,而出现错误。
Git
Feature of GIT
- Distributed
代码分布式:全球都可以共享
每一个开发者都有一个整个完整项目的本地备份,如果某个本地备份被修改了并且推送到了sever,则这种改变会发生在每份备份当中 - Compatible
SVN repository can be directly accessed using Git-SVN. - Non-Linear
支持非线性,而且通过分支实现了 tree data structure(not linear)
主分支:任何时候都是存在的,并且主分支包含了完整的成熟的代码
只有git 有branch 模型 在所有VCS工具中,而且只需要花费几秒钟就可以 create /delete/merge -branchs
- Lightweight
使用最无损的压缩技术在客户端压缩数据。 - Speed
从本地repository获取数据比从remote repository获取数据快100倍。
考虑到互联网的延迟等
GIT is one order of magnitude faster than other VCS tools
比其他工具快10倍。原因是,GIT是用C语言实现的,相比较其他高级语言,C更能直接操作硬件,获取更快的访问速度。 - Open Source
GIT 本身是开源的 - Reliable
On events of system crash, the lost data canbe easily reconverd from any of the local repositories of the collaborators - Secure
SHA1: to name and identify objects.
- Economical
What is a Repository
exclusively 专有的,唯一的
resides 居住
在git中对于文件上传有三个不同的阶段
- Working directory
untracked and modified files 在此阶段
当我们使用git status命令时,这些文件会被罗列出来 - Staging area
文件已经修改完成,从内容上具备了提交的条件,但是需要等待添加commit。
之所以存在这个阶段,是因为我们需要可以更加灵活的,针对每个文件添加相同的或者不同的commit。 - .git directory (commited file)
Git Operations & Commands
Git 安装(Linux)
我是在virtualenv环境下安装的,利用pip,注意包名不是git,是gitpython
pip install gitpython
检查一下版本,安装成功
(env1) dalechen@ubuntu:~/vir_env/env1$ git --version
git version 2.17.1
配置全局变量
作用是什么?
git config --global user.name "dalechen"
git config -- global user.email "dalebrown@qq.com"
检查配置情况
(env1) dalechen@ubuntu:~/vir_env/env1$ git config -l
user.name=DaleChen0351
user.email=dalechen0351@gmail.com
方式1:初始化本地仓库后关联远程仓库
描述作用
首先先进入到你打算同步到github上的文件夹内,这里我打算同步 git_test文件夹。注意
(env1) dalechen@ubuntu:~/vir_env/env1$ mkdir git_test
(env1) dalechen@ubuntu:~/vir_env/env1$ ls
bin exercice_2.png include lib myfolder share
etc git_test jupyter.log m-learning my_note
(env1) dalechen@ubuntu:~/vir_env/env1$ cd git_test
(env1) dalechen@ubuntu:~/vir_env/env1/git_test$
git init
cd命令进入本地创建的一个工作目录,也就是 git_test文件夹,后使用’git init’命令进行初始化;Git以后就会对该目录下的文件进行版本控制。
(env1) dalechen@ubuntu:~/vir_env/env1/git_test$ git init
Initialized empty Git repository in /home/dalechen/vir_env/env1/git_test/.git/
(env1) dalechen@ubuntu:~/vir_env/env1/git_test$
创建一个空的GIT仓库或重新初始化一个现有仓库(会生成一个.git的隐藏文件夹)
(env1) dalechen@ubuntu:~/vir_env/env1/git_test$ ls -al
total 24
drwxrwxr-x 4 dalechen dalechen 4096 Mar 27 10:01 .
drwxrwxr-x 12 dalechen dalechen 4096 Mar 27 09:46 ..
-rw-rw-r-- 1 dalechen dalechen 16 Mar 27 09:58 file1.txt
-rw-rw-r-- 1 dalechen dalechen 17 Mar 27 09:58 file2.txt
drwxrwxr-x 7 dalechen dalechen 4096 Mar 27 10:01 .git
drwxrwxr-x 2 dalechen dalechen 4096 Mar 27 09:59 my_dir
如果以后不打算将这个文件夹作为本地代码作为仓库,想恢复回init前的状态,只需要把这个.git隐藏文件删除即可。
git status
git status命令用于显示working directory和staging area的状态对比。
- 此命令能看到那些修改被暂存到了, 哪些没有, 哪些文件没有被Git tracked到。
- git status不显示已经commit到项目历史中去的信息。看项目历史的信息要使用git log.
git diff
可以通过 git diff 命令,查看变化的文件中的具体变化有哪些
git add
通过status命令,我们已经知道了working directory和staging area中文件的区别。那么通过git add 命令可以将working directory中的文件添加到staging area中。
-
如果我们想一次将所有文件都添加到Staging area,可以使用git add -A命令,否则我们就一个一个添加。
-
使用git add file1.txt 添加一个文件
-
如果想让已经添加到staging area的文件再返回到working directory,则使用git reset file.txt
比如 git reset file1.txt
另外也可以使用git rest (无参数)将所有staging area中的文件返回到working directory中,变成untracked 文件。 -
使用git add -A 一次添加所有文件到staging area
git commit
- 将staging area的文件移动到本地仓库中
(env1) dalechen@ubuntu:~/vir_env/env1/git_test$ git commit -m "first commit"
[master (root-commit) 8c1a6f6] first commit
3 files changed, 6 insertions(+)
create mode 100644 file1.txt
create mode 100644 file2.txt
create mode 100644 my_dir/hello.py
- 当staging area的文件都已经通过commit提交后, staging area 就会被清空了
(env1) dalechen@ubuntu:~/vir_env/env1/git_test$ git status
On branch master
nothing to commit, working tree clean
git log
可以查看提交的信息记录
- commit hash number : 该参数是唯一的
- author 作者
- commit message
到这里为止,我们已经成功的tracking了本地的项目,而且将这些项目的变更记录添加到了staging area 并进一步添加到了repository
git remote add
本地当前.git仓库下的项目和远端GitHub账号下的项目关联。
git remote add origin git://github.com/someone/another_project.git
- 这时候如果你需要将它放到远程服务器上,可在远程服务器上创建一个目录,并把可访问的URL记录下来,此时你就可以利用’git remote add’命令来增加一个远程仓库,上面的命令就会增加URL地址为’git: //github.com/someone/another_project.git’,名称为origin的远程服务器,以后提交代码的时候只需要使用 origin别名即可
- 远程服务器别名 origin 是和特定的一个URL相关联,且是在当前目录下操作,故如果退出当前目录,则应该没有此关联配置了。
- 实验:在FAW的上级菜单中所关联的origin (上一级为orgin)地址就不一样了。因此这里的远程主机 就是指代的URL(或者ssh地址)
- 可以关联对应的HTTP的地址,也可以是SSH的地址,区别在于,如果关联的是HTTP的地址的话,那么以后你push的时候需要输入github的账户和密码,如果是SSH的话就不需要了。
补充:
- 取消本地目录和远程URL的关联
git remote remove origin
(env1) dalechen@ubuntu:~/vir_env/env1/my_note$ git remote remove origin
(env1) dalechen@ubuntu:~/vir_env/env1/my_note$ git remote -v
(env1) dalechen@ubuntu:~/vir_env/env1/my_note$
可以看到取消之后,通过 git remote -v 确定本地仓库已经解除了远程仓库的绑定。
- 给本地目录再增加一个远程项目关联
git remote add anthor_origin https:…
git push
推送到远端
- git push命令 https://blog.youkuaiyun.com/sky1203850702/article/details/41344131
- git push 远程主机名 本地分支名:远程分支名
- git push -u origin master (远程分支名如果不存在就新建一个)
- git push origin master:远程master
更新本地仓库
git pull
pull操作
git pull 远程主机名 远程分支名:本地分支名
- git pull origin master:master
- git pull origin master(和当前分支合并)
git fetch
fetch操作
git fetch 远程主机名 远程分支名
- git fetch origin master
上述命令从远程refs/heads/命名空间复制所有分支,并将它们存储到本地的refs/remotes/ origin/命名空间中,除非使用分支..fetch选项来指定非默认的refspec。注:refs/remotes/ origin/就是指的localrepos。
所取回的更新,在本地主机上要用”远程主机名/分支名”的形式读取。比如origin主机的master分支,就可以用origin/master读取。参考下面的merge和rebase操作 - 自我理解
origin/master:指的就是本地暂存库,or 本地库的远程分支
orign master:指代远程库的远程分支
master:指的是本地库的本地分支
1 更新了refs/remotes/ origin/
2 更新到了fetch_head
3 并没有更新本地目录
git merge
命令用于将两个或两个以上的开发历史加入(合并)一起。
git merge origin/master
将分支dev合并到当前分支中,自动进行新的提交:
? git rebase origin/master
为什么远程分支有了更新之后,fetch之后,通过git status在本地对比,并没有出现区别
- git status命令用于显示工作目录和暂存区(staging area)的状态对比。哪些文件没有被Git tracked到。
- git status不显示已经commit到项目历史中去的信息。看项目历史的信息要使用git log.
推论:fetch 是直接更新了localrepos ? YES,直接存储到本地的 refs/remotes/ origin/命名空间中了。
如果这个时候强行push,会出现当前的branch (当前的branch指的是 working directory?)是落后于远程branch的。
克隆远程仓库到本地
从服务器仓库复制代码。我们想要同步一个服务器上的工程。你的公司有一个
语法:git clone <url地址> <目标本地地址>
- 先选择好一个文件夹,cs229
(env1) dalechen@ubuntu:~/vir_env/env1$ ls
bin etc git_test jupyter.log m-learning my_note share
cs229 exercice_2.png include lib myfolder python_note
(env1) dalechen@ubuntu:~/vir_env/env1$ cd cs229
(env1) dalechen@ubuntu:~/vir_env/env1/cs229$ ls
- git clone https://github.com/DaleChen0351/stanford-cs-229-machine-learning.git .
(env1) dalechen@ubuntu:~/vir_env/env1/cs229$ git clone https://github.com/DaleChen0351/stanford-cs-229-machine-learning.git .
Cloning into '.'...
remote: Enumerating objects: 390, done.
remote: Total 390 (delta 0), reused 0 (delta 0), pack-reused 390
Receiving objects: 100% (390/390), 21.23 MiB | 30.03 MiB/s, done.
Resolving deltas: 100% (244/244), done.
(env1) dalechen@ubuntu:~/vir_env/env1/cs229$
Others
git remote -v
远程仓库的信息
git branch
查看存在的分支
-
查看所有本地和远程的分支: git branch -a
-
查看本地分支:git branch
-
查看远程分支:git branch -r
-
git branch namebranch
新建分支
- git branch --merged
?
- git checkout namebranch
切换分支
- git branch -d namebranch
删除本地分支
- git push origin --delete namebranch
删除远程分支
合并分支
- 第一次 git commit后git才会默认新建分支,否则利用 git branch 命令查看 不会有任何分支
.gitignore file
- 在使用Git的过程中,我们喜欢有的文件比如日志,临时文件,编译的中间文件等不要提交到代码仓库,这时就要设置相应的忽略规则,来忽略这些文件的提交。
- 简单来说一个场景:在你使用git add .的时候,遇到了把你不想提交的文件也添加到了缓存中去的情况,比如项目的本地配置信息,如果你上传到Git中去其他人pull下来的时候就会和他本地的配置有冲突,所以这样的个性化配置文件我们一般不把它推送到git服务器中,但是又为了偷懒每次添加缓存的时候都想用git add .而不是手动一个一个文件添加,该怎么办呢?
- 很简单,git为我们提供了一个.gitignore文件只要在这个文件中申明那些文件你不希望添加到git中去,这样当你使用git add .的时候这些文件就会被自动忽略掉。
- 特殊问题
本地利用pycharm编写有一些代码,之前也利用git传递到了github的云端,使用中发现有一个.idea/的文件夹总是在我更新代码后也发生了变化,然后每次git status 时,它也被追踪了变化,但是我并不希望把它的变化也每次都上传到github。
所以,增加了一个.gitignore文件,将其地址写入.gitignore中,但是却发现,git 还是会对它的改变进行追踪,后来发现是因为
- .gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。
- 解决方 法就是先把本地缓存删除(改变成未track状态),然后再提交:
$ git rm -r --cached .idea/
引用
.gitignore的忽略规则及特殊问题相关参考