1.config git账户
1 | git config --global user.email fridayfang@zhaoxin.com |
以后这个将作为git commit 的签名,upload还需要ssh的public key (直接 ssh-keygen
),类似github的上传,添加collaborator需要对方的邮箱一样
2.git仓库的创建
git init
在当前目录下初始化一个git仓库git init --bare
初始化一个裸仓库 curDir ,裸仓库是专为多人协作而存在的仓库, 本身不会存放代码,代码靠别人push给他 (curDir最好是以.git结尾的目录)git clone zx@10.28.35.114:/home/zx/repository/zx_dvb.git
使用ssh协议从别处拉取一个git仓库 注意这里拉取的仓库应该是一个裸仓库,不然拉取后是没法修改的,因此比较适合个人在本地开发,用作版本管理git clone https://github.com/FFmpeg/FFmpeg.git
使用https协议拉取ffmpeg仓库git clone git@github.com:FFmpeg/FFmpeg.git
使用ssh拉取github保管的ffmpeg仓库
(以后若该代码发生了更新,需要resync, 只需要在.git所在目录 git pull (此过程伴随着merge操作)即可)
3. 分支上版本管理
git log
查看.git 中的版本历史栈,包含 commit id)git reflog
查看所有的 git commit-id 历史,包含历史和回退前的commit id。就算原来不在任何branch上,只要有那笔提交的commit-id,就可以回退到那里)git log --author=fridayfang
只看某人的提交git log --stat
查看每次提交都对哪些文件做了改动 (版本之间的 git status,git show --stat <commit-id>
是查看某一次的文件改动)git diff .
(查看当前工作目录相对于 stage 的改动)git diff <old> <new>
(查看新版本相对旧版本改动了什么)git diff <old> <new> .
(查看新版本和旧版本当前文件夹下的改动)git diff <old> <new> --stat
(查看新版本和旧版本之间哪些文件发生了改动)git diff <old> <new> a.c
(查看新版本和旧版本当前文件的改动)git diff --cached
查看stage相对于上次commit的改动git show <commit-id> <xx.c>
查看某一个commit所做的改动(即某一commit相对与其前一版本之间的git diff)git show <commit-id> --stat
查看某一个commit所做的改动,只看相对与其前一版本修改了哪些文件git reset--hard <commit-id>
通过commit-id 使整个project在本地版本之间穿梭(commit–>stage–>workspace)git reset <commit-id>
使stage恢复到commit-id对应的状态(commit–>stage,不改变workspace)git status
(查看工作目录状态,哪些被修改了? 有没有添加到 stage?)git checkout <commit-id> file
只让某个文件在回到某个版本的状态 (而不是整个project)git checkout <commit-id> directory/
让某个文件夹整个恢复到 某个 commit 的状态git checkout <commit-id>
以当前branch的最新commit-id为base,new一个tmp分支(匿名branch)并切过去(作用在整个project上),一旦从tmp分支切走,tmp分支将自动消失.所以万一在tmp分支上做了提交,且想保存他,可以再以tmp分支为base新建一个branch
checkout和reset区别 在于checkout 不生成,不改变,不回退commit. 而 reset是真的在版本之间穿梭,会更改commit-id的git rm -rf xxx
(删除stage中对应文件,同时工作目录中的对应文件也被删除)git rm -rf --cached xxx
(只删除stage中的对应文件)git add .
(将当前工作目录下的所有文件添加到 stagegit commit -s
(以stage的内容提交到 git 仓库)git commit --amend
(以stage的内容提交到 git 仓库,与上版本commit id 相同,即作为附加提交)git clean -f -d <path>
(亦可简写为git clean -fd <path>
)删除某个路径下的所有 Untracked 文件&文件夹(去掉-d则只删除文件)
4. git 分支管理
git branch
查看本机上的所有branchsgit branch -a
查看git 仓库管理的所有branchs, 包括服务器端,本地 git clone 的时候其实默认是拉取了mater分支+其他分支的信息,所以这个操作是ok的1
2
3
4
5git branch -a
*master (我们 git clone 的时候 本地默认创建 master 分支并追踪 服务器上的 origin/master )
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/developgit branch abc
在本地基于当前branch的最新提交 创建新branch abcgit branch -D abc
删除本机上的某个 branchgit push origin :abc
删除github上某个branch, github会在远程执行删除abc branch的动作git checkout abc
切换到分支abc上,当当前branch上有未提交的更改时,此操作不确定会怎样,git会将这些改动带到branch abc上,有的会切不过去,最保险操作是将更改commit,方便管理也很安全git checkout -b abc
新建branch abc并切过去,等效于git branch abc 新建分支
&&git checkout abc 切到这个分支
(repo start 应该就是做了这个)git checkout -b abc <origin/develop>
以服务器上develop branch的最新commit-id为base,new一个 abc branch并切过去,注意以后 git push origin abc,若服务器上不存在 abc branch 则会新创建。若刚好存在名叫 abc 的branch则执行新的commit,因此如果checkout的这个branch以后想继续提交回服务器,abc名字必须是develop,否则需要先 git checkout -b xxx 改branch的名字^_^git cherry-pick <commit-id>
将另外一个branch的某一个commit应用到当前分支上(会产生一个新的commit),且很可能会发生冲突,比如服务器端想cherry-pick 本地2 上B那一笔,解决冲突还是modify-add-commitgit cherry-pick <commit-id0> <commit-id1> …
将另外一个branch上的某几个commit应用到当前分支上(会产生n个commit,若不想产生n个commit,需要使用 –no-commit选项)git merge <branch>
某个branch上自 分出去开始 所有的改动应用到当前分支上git merge <commit-id> --squash
将某个branch上自 分出去开始 到commit为止的所有改动应用到当前分支上git format-patch <prev-commit-id>
基于当前最新的commit,产生一个相对于 prev-commid-id的补丁(.patch文件,其实就是一个diff)git apply xxx.patch
在目前最新commit-id的基础上打补丁(不会做任何提交,git status会看到好多文件做了改动),补丁多用于不同仓库之间
5. 多人协作
5.1. 新建一个服务器仓库:
在某个目录下(最好.git结尾,例如 abc.git/ ,内容为空)
git init --bare
这样服务器端的仓库便搭建完成了
5.2. 上传代码:
git init
创建本地仓库Agit add .
git commit -s
then 本地仓库创建完成git remote -v
可以查看远程urlgit remote add FD ssh://root@10.28.35.173:/root/Desktop/abc.git
添加一个远程仓库(并默认追踪其master分支),路径指定为ssh://root@10.28.35.173:/root/Desktop/abc.git
,以后使用 FD 来指代它.- 若FD是默认的origin,则以后git push 本地master分支 / git pull 到本地master可以省略origin和master
- 如果想追踪服务器上的其他分支,需要本地 checkout 并指定追踪 FD/xxBranch(见上面的 git branch 和 git checkout 那里)
- 以后若想修改远程仓库的url,可以
git remote set-url origin ssh://fang@10.28.35.173:/home/fang/codes/caffe_zxnn.git
git push FD master
将本地 .git 仓库的master分支push到 FD远程仓库(远程不存在master则创建,存在则会commit) git push 前记得先 git pull ,git push 不带任何参数则是 默认的 origin 和 本地已存在的mastergit pull FD master
将远程仓库FD的 master分支拉取到branch上,若 FD/master 上有比本地 branch 更新的提交则会执行merge操作,若本地原是空的,则会创建一个master分支
5.3. 下载代码:
git clone root@10.28.35.173:/root/Desktop/abc.git
//这将会在本地B 创建一个目录abc/,然后sync最新代码,远程的代码仓库在本地被称作origin(默认的名字)git clone http://10.28.251.102/zhaoxin/android_kernel_3.18
(http 的匿名方式)git clone http://fridayfang@10.28.251.102/zhaoxin/android_kernel_3.18
git clone ssh://fridayfang@10.28.251.102:29418/zhaoxin/android_kernel_3.18
git clone URL
等价于git init
+git remote add origin ssh://root@10.28.35.173:/root/Desktop/abc.git
+git pull origin master
,经过实验发现 貌似 git clone 得到的信息更多, git pull 之后 git branch -a 貌似看不到远端的所有branch
TIPS:
- git remote -v 便可以看到remote的URL 叫啥(git config -e 也可以)
- 几个可能发生冲突的情况
1
Updates were rejected because the remote contains work that you do not have locally. 提示你 git push 前必须先 git pull
git merge <branch>
在本地merge某一个branch的修改git pull <origin> <master>
拉取git clone时候指定的那个仓库到本地git push origin master
本地将本地代码推送到远程(git clone时候指定的那个仓库,只要git pull时候冲突解决了,这里就不应该在出现冲突了)
一旦发生冲突,会有类似如下的错误提示。1
2CONFLICT (content): Merge conflict in xxx.c
Automatic merge failed; fix conflicts and then commit the result
此时发生冲突的xxx.c会被git改写(主要是添加了<<<<<<< ======= 以及>>>>>>>等标记 )1
2
3
4
5
6
7
8
9
10<<<<<<< HEAD (这部分是原有代码a)
int funcAdd(int a,int b)
{
int c = a+b;
return c;
======= (这部分是企图merge时候发生了冲突的那部分代码)
void funcAdd(int a, int b)
{
int c = a+b;
>>>>>>> 60e468f9ae65f6f480036e79acda6bc6baadc8d6
- git多分支开发的时候,如果当前branch的当前workspace的改动没有提交到本branch上,那么切换到别的branch上也是可以看到的。如果改动提交到了本branch上,那么这个commit就属于本branch,切换到别的branch的时候就看不到,别的branch就只能merge或者cherry-pick。所以最好养成及时将本地改动 commit 的习惯,不仅防止数据丢失(即使git reset –hard 也是可以通过 git reflog 找回),也可以避免在切branch的时候出现意想不到的问题。
- repo sync 的时候,如果当前工作目录下有未提交的 改动,他会 sync 到最新代码后,尝试将改动 作用到最新代码上! 成功了的话不会给你提示的 !