[已迁移]使用git管理代码仓库


GIT

1 Git vs SVN

Git是分布式的,SVN是集中式的 

 

  • Git复杂概念多,SVN简单易上手
  • Git分支廉价,SVN分支昂贵

在版本管理里,分支是很常使用的功能。在发布版本前,需要发布分支,进行大需求开发,需要 feature 分支,大团队还会有开发分支稳定分支等。在大团队开发过程中,常常存在创建分支,切换分支的需求。

Git 分支是指针指向某次提交,而 SVN 分支是拷贝的目录这个特性使 Git 的分支切换非常迅速,并且创建成本非常低

而且 Git 有本地分支,SVN 无本地分支。在实际开发过程中,经常会遇到有些代码没写完,但是需紧急处理其他问题,若我们使用 Git,便可以创建本地分支存储没写完的代码,待问题处理完后,再回到本地分支继续完成代码。

 

2 git核心概念

Git 最核心的一个概念就是工作流。

  • 工作区(Workspace)是电脑中实际的目录。

  • 暂存区(Index)类似于缓存区域,临时保存你的改动。

  • 仓库区(Repository),分为本地仓库和远程仓库。

一般来说,记住以下命令,便可进行日常工作了

 

3 初始化

安装服务器

centos 7
yum install git

rhel6
wget -c https://mirrors.edge.kernel.org/pub/software/scm/git/git-1.8.4.tar.gz
yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
./configure --prefix=/usr
make all doc
make install install-doc install-html
编译的报错忽略

  

Git global setup
git config --global user.name "高涛"
git config --global user.email "gaotao@huored.com"

Create a new repository 新建repo
git clone git@gitlab.ops.net:gaotao/test.git
cd test
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master


Existing folder 已存在的目录
cd existing_folder
git init
git remote add origin git@gitlab.ops.net:gaotao/test.git
git add .
git commit -m "Initial commit"
git push -u origin master

Existing Git repository 本地已存在的一个repo
cd existing_repo
git remote rename origin old-origin
git remote add origin git@gitlab.ops.net:gaotao/test.git
git push -u origin --all
git push -u origin --tags

   

4 配置

# 列举所有配置
$ git config -l

# 为命令配置别名
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.st status
$ git config --global alias.br branch

# 设置提交代码时的用户信息
$ git config [--global] user.name "[name]"
$ git config [--global] user.email "[email address]"
$ git config remote.origin.url git@github.com:richardzgt/AssetMP.git

使用ssh方式可以免密码
git remote add origin git@github.com:richardzgt/PyLogin.git

Git 用户的配置文件位于 ~/.gitconfig

Git 单个仓库的配置文件位于 ~/$PROJECT_PATH/.git/config

 

5 增删文件

# 添加当前目录的所有文件到暂存区
$ git add .

# 添加指定文件到暂存区
$ git add <file1> <file2> ...

# 添加指定目录到暂存区,包括其子目录
$ git add <dir>
$ git mv [file-original] [file-renamed]

# 删除工作区文件,并且将这次删除放入暂存区
git rm <file>

# 停止追踪指定文件,但该文件会保留在工作区
git rm -r --cached .venv
git rm --cached Pipfile.lock

# 删除仓库上的文件
git remote rm <file>

在.gitignore配置不需要同步的文件
*.lock
.venv
*.log

    

6 分支

# 列出所有本地分支
$ git branch
 
# 列出所有本地分支和远程分支
$ git branch -a
 
# 新建一个分支,但依然停留在当前分支
$ git branch [branch-name]
 
# 新建一个分支,并切换到该分支
$ git checkout -b [new_branch] [remote-branch]
 
# 切换到指定分支,并更新工作区
$ git checkout [branch-name]
 
# 合并指定分支到当前分支
$ git merge [branch]

# 选择一个文件合并到分支/master
git checkout master  # 切换到master
git checkout --patch aliyun_api xdiscovery/plugins/aliyun.py  # 把aliyun_api这个分支的某个文件合并到当前分支(master)
 
# 选择一个 commit,合并进当前分支
$ git cherry-pick [commit]

# 删除本地分支,-D 参数强制删除分支
$ git branch -d [branch-name]
 
# 创建远程分支(本地分支push到远程)
git push origin [name]

# 删除远程分支
$ git branch -a
* master
  remotes/origin/master
  remotes/origin/v1.0
$ git push origin  --delete v1.0

  

7 tag(标签)

# 创建标签
先切换到对应的branch分支
git tag v1
git tag -a v1 -m "0.1.2版本"

# 切换标签和分支相同
git checkout [tagname]


# 推送到远程
git push origin v1
或者 git push origin --tags 把所有的本地标签一次性推上去


# github 中删除release/tag只能在命令行执行,不能在界面点击操作
git tag -d [tag] 
git push origin :[tag]   

比如要操作一个v1的标签
git tag -d v1
git push origin :v1

  

 

8 提交

# 提交暂存区到仓库区
$ git commit -m [message]

# 提交工作区与暂存区的变化直接到仓库区
$ git commit -a

# 提交时显示所有 diff 信息
$ git commit -v

# 提交暂存区修改到仓库区,合并到上次修改,并修改上次的提交信息
$ git commit --amend -m [message]

# 上传本地指定分支到远程仓库
$ git push [remote] [remote-branch]

  

9 拉取

# 下载远程仓库的所有变动
$ git fetch [remote]

# 显示所有远程仓库
$ git remote -v

# 显示某个远程仓库的信息
$ git remote show [remote]

# 增加一个新的远程仓库,并命名
$ git remote add [remote-name] [url]

# 删除远程仓库
$ git remote rm [name]

# 修改远程仓库
$ git remote set-url --push[name][newUrl]

# 推送远程仓库
$ git push [remoteName] [localBranchName]

# 取回远程仓库的变化,并与本地分支合并
$ git pull [remote] [branch]

# 取回远程仓库的变化,并与本地分支变基合并
$ git pull --rebase [remote] [branch]

    

10 撤销

# 恢复暂存区的指定文件到工作区(比如文件在工作区被删除,就要从暂存区恢复,但是首先先要commit到暂存区),使用git status先看下状态
$ git checkout [file]

# 恢复暂存区当前目录的所有文件到工作区
$ git checkout .

# 恢复工作区到指定 commit,比如master、tag_name、commit_id
$ git checkout [commit]

# 重置暂存区的指定文件,与上一次 commit 保持一致,但工作区不变
$ git reset [file]

# 重置暂存区与工作区,与上一次 commit 保持一致
$ git reset --hard

# 重置当前分支的指针为指定 commit,同时重置暂存区,但工作区不变
$ git reset [commit]

# 重置当前分支的HEAD为指定 commit,同时重置暂存区和工作区,与指定 commit 一致
$ git reset --hard [commit]
git log // 查看版本后
git reset --hard 261896678417746b5b932a2865aa3f2728d63c2e //恢复到指定版本
git reset --hard HEAD^ // 回复到上个版本

# 新建一个 commit,用于撤销指定 commit
$ git revert [commit]

# 将未提交的变化放在储藏区
$ git stash

# 将储藏区的内容恢复到当前工作区
$ git stash pop

# 查看stash空间的内容
$ git stash show

          

git stash

    1、git stash

        备份当前工作区的内容,保存到git 栈中,从最近的一次commit中读取相关内容

    2、git pull  或者做其他的工作    

    3、git stash pop

        从git栈中获取到最近一次stash进去的内容,恢复工作区的内容。。获取之后,会删除栈中对应的stash。。

        由于可能会stash多次,git使用栈管理,我们可以使用git stash list查看所有的stash

    git stash list

        显示git栈中的所有工作区内容的备份,

        比如使用git stash apply stash@{1},就可以把版本号为stash@{1}的备份取出,不会删除对应的stash。。0为最新版本

    git stash clear

        清空git栈

  还可以git reset --hard放弃本地修改,然后就可以git pull了。。但是不推荐使用gitreset --hard指令,实在是太危险啦!

但是git stash pop取出备份的时候也会出现冲突

比如,有个文件login.java,,你修改了一段代码,git stash保存以后,你从服务器上继续git pull了别人的代码,,

如果此时,别人的代码也修改了login.java。。。

此时当我们使用git stash pop 的时候,就会发生冲突,因为我们的修改不是基于最新的pull下来的文件的基础上。。所以git很难判断,

解决方法:

    备份我们修改后的文件,,删除程序文件中我们所做的修改,重新pull,,然后在用我们备份好的文件替换掉,,再push上去即可。。

 

 

11  查询

# 查看工作区文件修改状态
$ git status 

# 查看版本库修改记录,列出所有对此文件修改的历史记录
$ git log 
git log ucloud_uhas_api.py

# 查看某个文件的历史具体修改内容,列出所有修改内容,十分实用
$ git log -p [file] 

# 查看工作区文件修改具体内容 
$ git diff [file]

# 查看暂存区文件修改内容
$ git diff --cached [file] 


# 查看某人提交记录
$ git log --author=someone 


# 查看某次提交具体修改内容
$ git show [commit]

# 查看某个文件的更新
git show 4e3f163788608c0a354f9c690fd456c618a17b3d ucloud_uhas_api.py
git show 73c023dadc5a1fa5540d47eefae083bdebac7745 ucloud_uhas_api.py

  

    

12 代码合并

当仓库代码和本地已提交的代码冲突时,会提示:

更新 77582d4..702d425
error: 您对下列文件的本地修改将被合并操作覆盖:

1 我们可以使用强行更新掉:

git fetch

git reset --hard origin/master
HEAD 现在位于 702d425 [FIX] update the pipfile, correct `pymysql` version as `0.9.3`

git pull 
已经是最新的。

 

2 手工处理有冲突的部分

$ git pull
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 6 (delta 4), reused 2 (delta 0)
展开对象中: 100% (6/6), 完成.
来自 gitlab.ops.net:mlyw/vm_manager
30460e4..fe01e2b master -> origin/master
更新 30460e4..fe01e2b
error: 您对下列文件的本地修改将被合并操作覆盖:
script/dev/docker/start.sh
请在合并前提交您的修改或者保存进度。
终止中



$ git status
位于分支 master
您的分支落后 'origin/master' 共 1 个提交,并且可以快进。
  (使用 "git pull" 来更新您的本地分支)
尚未暂存以备提交的变更:
  (使用 "git add <文件>..." 更新要提交的内容)
  (使用 "git checkout -- <文件>..." 丢弃工作区的改动)

	修改:     start.sh

未跟踪的文件:
  (使用 "git add <文件>..." 以包含要提交的内容)

	../../../conf/1

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

  

  git pull远程仓库出错,本地冲突没有add也没有commit到本地仓库

git merge start.sh
merge:start.sh - 不能合并

  用merge提示不能合并

 

$ git add start.sh
$ git commit -m '[merge] start.sh'

  把冲突文件先提交到本地仓库

 

$ git merge start.sh
error: 无法合并,因为您有未合并的文件。
提示:请在工作区改正文件,然后酌情使用 'git add/rm <文件>' 命令标记
提示:解决方案并提交。
fatal: 因为存在未解决的冲突而退出。

  没发自动merge,只能手工咯

 

vi start.sh

#!/bin/bash
<<<<<<< HEAD
# @Author: gaotao99
=======
# @Author: gaotao100
>>>>>>> fe01e2be0d4bc0271c934db1a618bc89a64aab7e
# @Date:   2018-05-10 10:53:09
# @Last Modified by:   gaotao
# @Last Modified time: 2018-05-23 18:35:06
RUN_SCRIPT='run.sh'
WORK_DIR="/bench/app/deploy/"
UTIL_URL="http://yum.ops.net/script/docker/run.sh"
source include/linux/setenv.sh
retry=10
count=$retry

  远程仓库和本地仓库的差异就会显示出来,删除或者保留直接编辑操作

 

$ git add start.sh
$ git commit -m '[merge] start.sh' 
$ git push
对象计数中: 7, 完成.
Delta compression using up to 8 threads.
压缩对象中: 100% (7/7), 完成.
写入对象中: 100% (7/7), 583 bytes | 0 bytes/s, 完成.
Total 7 (delta 5), reused 0 (delta 0)
To gitlab.ops.net:mlyw/vm_manager.git
   fe01e2b..9ab7dae  master -> master

  最后再提交一次完事

 

13  git commit message 的格式

每次提交,Commit message 都包括三个部分:Header(必须),Body 和 Footer可选。

Header部分只有一行,包括三个字段:type(必需)、scope(可选)和subject(必需)。

1)type

[FEAT]:新功能(feature)
[FIX]:修补bug
[DOCS]:文档(documentation)
[STYLE]: 格式(不影响代码运行的变动)
[REFACTOR]:重构(即不是新增功能,也不是修改bug的代码变动)
[TEST]:增加测试
[CHORE]:构建过程或辅助工具的变动

  如果typefeatfix,则该 commit 将肯定出现在 Change log 之中。其他情况(docschorestylerefactortest)由你决定,要不要放入 Change log,建议是不要

2)scope

scope用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。

(3)subject

subject是 commit 目的的简短描述,不超过50个字符。

  • 以动词开头,使用第一人称现在时,比如change,而不是changedchanges
  • 第一个字母小写
  • 结尾不加句号(.

  

14 遇到过的一些问题

git clone 时出现 fatal: Unable to find remote helper for ‘http’ 的解决方式

1 找到 git-core
2 加到环境变量里面: /usr/libexec/git-core:$PATH

(gnome-ssh-askpass:29241): Gtk-WARNING **: cannot open display:
1 unset SSH_ASKPASS


git push //或者git push -u origin master

  

error: The requested URL returned error: 401 Unauthorized while accessing http://git.wangshibo.net:8081/weixin/weixin.git/info/refs

error: Your local changes to the following files would be overwritten by merge:
protected/config/main.php
Please, commit your changes or stash them before you can merge.

  

Git代码冲突常见解决方法:
在代码的.git/config文件内[remote "origin"]的url的gitlab域名前添加gitlab注册时的“用户名:密码@”
url = http://gaotao:30402104@gitlab.ops.net/gaotao/dev-nginx-config.git

error: Your local changes to the following files would be overwritten by merge:
解决办法:
如果希望用代码库中的文件完全覆盖本地工作版本:
git reset --hard
git pull
如果希望保留生产服务器上所做的改动,仅仅并入新配置项,
git stash
git pull
git stash pop


Merging is not possible because you have unmerged files

这个出题出现在代码合并的过程上,原因是不仅是remote的文件代码变了,本地的文件代码也变了,所以造成了冲突。

If you have fixed the conflicts you need to add the files to the stage with git add [filename], then commit as normal.

用git diff或者git status 查看哪些文件冲突,有冲突的会提示:


就是你手动修改git提示有错误的文件,修改之后,添加有冲突的文件: git add [被修改的冲突文件], 最后,按照普通提交那样,提交有冲突的问题: git commit [修改后的冲突文件] -m “注释内容”


 15 gitlab server

配置git对接ldap服务器

     label: 'LDAP'
     host: '10.0.0.200'
     port: 389
     uid: 'uid'
     method: 'plain' # "start_tls" or "simple_tls" or "plain"
     bind_dn: 'CN=Manager,DC=xxxx,DC=com'
     password: 'XXXXX'
     base: 'DC=xxxx,DC=com'

  

gitlab-ctl  reconfigure

gitlab-ctl restart/tail 

  

配置邮箱

# gitlab-rails console
Loading production environment (Rails 4.2.8)
irb(main):001:0> 
irb(main):002:0* 
irb(main):003:0* 
irb(main):004:0* 
irb(main):005:0* Notify.test_email("xufei_@hotmail.com","nihao","gitlab").deliver_now

Notify#test_email: processed outbound mail in 183.0ms

Sent mail to xufei_@hotmail.com (53.2ms)
。。。。。。。。。。。。

  

16 备份恢复

首先两个服务器先做互信

# 备份脚本 git_bak.sh
#!/bin/bash
#
BACK_DIR="/var/opt/gitlab/backups"
rm -rf ${BACK_DIR}/*
gitlab-rake gitlab:backup:create
cd $BACK_DIR 
FILE=$(ls -r *.tar|head -1)
scp $FILE 10.4.230.9:${BACK_DIR}



# 恢复脚本 git_restore.sh
#!/bin/bash
BACK_DIR="/var/opt/gitlab/backups"
cd $BACK_DIR
latest_file=$(ls -r *.tar|head -1)
chmod 777 $latest_file
sub_file=$(echo $latest_file|awk -F"_gitlab" '{print $1}')
echo $sub_file
gitlab-ctl stop unicorn
gitlab-ctl stop sidekiq
gitlab-rake gitlab:backup:restore BACKUP=${sub_file} force=yes     # 强制执行
if [ $? -eq 0 ]; then
	echo "restore success"
	gitlab-ctl reconfigure               
	gitlab-ctl restart                                                      # 要有3分钟的等待时间
        cd $BACK_DIR
        ls *.tar|grep -v $latest_file|xargs rm -rf                   # 只保留一个文件
        rm -rf /var/opt/gitlab/git-data/repositories.old.*       # 删除历史临时repository文件
else
	echo "restore failed!"
fi

  

  

 svn

1 下载

svn checkout svn://192.168.21.103/

非交互式
svn --username=xxxx --password=xxxxxx -q checkout http://huored.gicp.net:8088/svn/xxxxx/trunk ./ --non-interactive --trust-server-cert 

  

2 导入

导入项目文件(导入在根目录上)
sudo svn import PythonLearn svn://192.168.21.103/ -m "import"

  

3 更新

SVN update  将版本库的修改合并到工作副本中
svn commit 
svn list svn://183.129.172.71/PythonLearn/Project/MyStock
svn checkout svn://183.129.172.71/Project/jumpserver-master​

更新到指定版本
svn checkout http://ip/trunk ./ -r 308 

  

4 删除

svn delete svn://183.129.172.71/PythonLearn/Project/Salt/srv -m 'delete salt'

  

5 查看

注意 加了username可以指定用户(可能默认下用户不能登录)
svn --username=gaotao list http://huored.gicp.net:8088/svn/opscript


1)svn status path(目录下的文件和子目录的状态,正常状态不显示) 
【?:不在svn的控制中;M:内容被修改;C:发生冲突;A:预定加入到版本库;K:被锁定】 
2)svn status -v path(显示文件和子目录状态) 
第一列保持相同,第二列显示工作版本号,第三和第四列显示最后一次修改的版本号和修改人。 
注:svn status、svn diff和 svn revert这三条命令在没有网络的情况下也可以执行的,原因是svn在本地的.svn中保留了本地版本的原始拷贝。 
简写:svn st 
或者直接svn delete test.php 然后再svn ci -m ‘delete test file‘,推荐使用这种 
简写:svn (del, remove, rm)


查看日志 
svn log path 
例如:svn log test.php 显示这个文件的所有修改记录,及其版本号的变化 
9、查看文件详细信息 
svn info path 
例如:svn info test.php 
 

 

6 问题处理

/usr/bin/env LC_ALL=C svn log --xml -l 30 --username='zgt' --password='xxx' --non-interactive --trust-server-cert
subversion/libsvn_repos/log.c:1073: (apr_err=220001)
svn: Item is not readable

处理:
修改服务器 authz 文件,把 读权限加到每个库上
[repository:/]
scmroad = rw
||
||
VV
[repository:/]
*=r
scmroad = rw

  

svn: 方法 OPTIONS 失败于 200 OK

1 将 10.0.0.199 huored.gicp.net 配置到 /etc/hosts
2 rm -rf ~/.subversion/auth/svn.simple/*

  

7 svn server

./configure --prefix=/usr/local/svn --with-apxs=/usr/local/httpd-2.2.19/bin/apxs --with-apr=/usr/local/apr/bin/apr-1-config --with-apr-util=/usr/local/apr-util/bin/apu-1-config --with-ssl --with-sqlite=/usr/local/sqlite --with-neon=/usr/local/neon --with-zlib=/usr --enable-maintainer-mode​


启动
/usr/local/subversion/bin/svnserve -r /usr/local/subversion/svndata/repos -d​

  

 

posted @ 2019-03-01 17:44  richardzgt  阅读(751)  评论(0编辑  收藏  举报