ddddfang's Blog.

git

字数统计: 2.7k阅读时长: 11 min
2019/01/11 Share

1.config git账户

1
2
3
git config --global user.email fridayfang@zhaoxin.com
git config --global user.name fridayfang
git config -e 查看git 的一些配置信息

以后这个将作为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 . (将当前工作目录下的所有文件添加到 stage
  • git commit -s (以stage的内容提交到 git 仓库)
  • git commit --amend (以stage的内容提交到 git 仓库,与上版本commit id 相同,即作为附加提交)

  • git clean -f -d <path> (亦可简写为 git clean -fd <path>)删除某个路径下的所有 Untracked 文件&文件夹(去掉-d则只删除文件)

git01

4. git 分支管理

  • git branch 查看本机上的所有branchs
  • git branch -a 查看git 仓库管理的所有branchs, 包括服务器端,本地 git clone 的时候其实默认是拉取了mater分支+其他分支的信息,所以这个操作是ok的

    1
    2
    3
    4
    5
    git branch -a
    *master (我们 git clone 的时候 本地默认创建 master 分支并追踪 服务器上的 origin/master )
    remotes/origin/HEAD -> origin/master
    remotes/origin/master
    remotes/origin/develop
  • git branch abc 在本地基于当前branch的最新提交 创建新branch abc

  • git branch -D abc 删除本机上的某个 branch
  • git 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-commit
  • git 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会看到好多文件做了改动),补丁多用于不同仓库之间

git01

5. 多人协作

5.1. 新建一个服务器仓库:

在某个目录下(最好.git结尾,例如 abc.git/ ,内容为空

  • git init --bare 这样服务器端的仓库便搭建完成了
5.2. 上传代码:
  • git init 创建本地仓库A
  • git add .
  • git commit -s then 本地仓库创建完成
  • git remote -v 可以查看远程url
  • git 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 来指代它.
    1. 若FD是默认的origin,则以后git push 本地master分支 / git pull 到本地master可以省略origin和master
    2. 如果想追踪服务器上的其他分支,需要本地 checkout 并指定追踪 FD/xxBranch(见上面的 git branch 和 git checkout 那里)
    3. 以后若想修改远程仓库的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 和 本地已存在的master
  • git 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:

  1. git remote -v 便可以看到remote的URL 叫啥(git config -e 也可以)
  2. 几个可能发生冲突的情况
    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
2
CONFLICT (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

  1. git多分支开发的时候,如果当前branch的当前workspace的改动没有提交到本branch上,那么切换到别的branch上也是可以看到的。如果改动提交到了本branch上,那么这个commit就属于本branch,切换到别的branch的时候就看不到,别的branch就只能merge或者cherry-pick。所以最好养成及时将本地改动 commit 的习惯,不仅防止数据丢失(即使git reset –hard 也是可以通过 git reflog 找回),也可以避免在切branch的时候出现意想不到的问题。
  2. repo sync 的时候,如果当前工作目录下有未提交的 改动,他会 sync 到最新代码后,尝试将改动 作用到最新代码上! 成功了的话不会给你提示的 !

多分支开发时候的几个有用命令

CATALOG
  1. 1. 1.config git账户
  2. 2. 2.git仓库的创建
  3. 3. 3. 分支上版本管理
  4. 4. 4. git 分支管理
  5. 5. 5. 多人协作
    1. 5.0.0.1. 5.1. 新建一个服务器仓库:
    2. 5.0.0.2. 5.2. 上传代码:
    3. 5.0.0.3. 5.3. 下载代码:
  • 5.1. TIPS: