Git

ooowl
  • 代码之外
  • Git
About 11 min

Git操作

初始化

这是简单指南,可以放在收藏夹想不起来了拿起来看看.
装好之后先配置一下账户。

/etc/gitconfig 是系统级别的配置,使用--system,这些配置是会按级别覆盖的,仓库覆盖账户覆盖系统
~/.gitconfig 下是账户级别的配置
git config --global user.name "ooowl"
git config --global user.email "2411708618aqq.com"
作者是谁,仓库commit会有你的名字,名字和email(名字可以重复但email一般唯一)并不作为身份标识,只是一个标记而已所有的独立提交不记名只验证公钥或github账号,你可以通过这样来查看
git config --local user.name
git config --local user.email
git init就会在该目录下生成一个.git文件夹,想知道这个文件夹里面是什么就自己去搜。
git config --xxxx --list 显示本级下git 的配置

📌Tip

个人习惯git commit的信息类型[add,delete,fix,feature,end]-此功能第几次提交-其他描述 其实这个是有明确规范名的,小项目无所谓,大项目看项目需要,遵守github定义的规范还可以自动生成change logs

查看

git status 看看自己目前仓库里未跟踪的文件,修改未提交的文件

600

不用说的命令

git --version
git clone 克隆项目
git add (.) 把文件添加到暂存区,未跟踪的文件可以直接添加为跟踪
git fetch 从更新分支状态
git pull
git commit -m "提交信息"

不常用但可能用到的命令

git show (id or tag) 查看这次id和tag的详细信息,包括提交时间作者提交了什么更改
git log (--oneline --all --graph ) 查看所有的提交记录,回滚需要至少7位id,-p查看提交具体干了啥,--all查看所有的分支,--graph 尽可能用图形表示。
git blame File 查看File的更改提交历史 it rebase 不要用,会变基!!!

分支管理

300 你可以认为 HEAD(大写)是"current branch"(当下的分支)。当你用git checkout切换分支的时候,HEAD 修订版本重新指向新的分支。有的时候HEAD会指向一个没有分支名字的修订版本,这种情况叫”detached HEAD“
head(小写)是commit对象的引用,每个head都有一个名字(分支名字或者标签名字等等),但是默认情况下,每个叫master的repository都会有一个head, 一个repository可以包含任意数量的head。在任何时候,只要这个head被选择成为”current head“,那么这个head就成了HEAD,总是大写

先命令

git branch # 列出分支
git branch -vv # 列出分支和远程分支的关系

git branch dev 或者 git checkout -b dev # 创建一个新的分支 或者 创建一个新的分支并且切换过去


当你切换分支的时候,Git 会用该分支的最后提交的快照替换你的工作目录的内容, 所以多个分支不需要多个目录

ignore参考

gitignore语法模板open in new window

  1. # 此为注释
  2. *.a 忽略所有.a结尾的文件
  3. !lib.a 但lib.a除外
  4. /todo 仅仅忽略项目根目录下的todo文件,不包括subdir/todo
  5. build/* 忽略build/目录下的所有文件
  6. doc/*.txt忽略doc/notes.txt(只忽略doc下本身的文件),但不包括doc/server/arch.txt(子目录下的文件)
  7. 原来已经被跟踪的文件是无效的,必须先取消跟踪git rm --cache,下次提交就不会生效了
  8. .idea/**/* 忽略某个(idea)文件夹下所有的文件和子文件夹(递归忽略所有)

服务器Git repo

申请用户

申请用户并设置密码,申请git组,把用到的用户加到这个组里,一般git就够了

groupadd git 
useradd git -g git
passwd git

每个用户单独的ssh K,这样就可以一个用户对应一个工程互不影响,多个工程只要申请多个用户,放到git用户组更管理就可以了.
设置用户只能使用git禁止登陆ssh,并修改密码,编辑/etc/passwd

git:x:502:504::/home/git:/bin/bash //找到这一行
git:x:502:504::/home/git:/bin/git-shell//改为这个

添加客户机的公钥

你也可以不添加直接ssh克隆,但是这样会每次都让你输入密码,只把开发记得公钥添加就行了
首先在你的客户机上cmd运行

ssh-keygen -t rsa -C "xxxxx@mail.com" 
//最后的是公钥里面显示的名字,自己开心就行

这样在下就得到了一对公钥和私钥id_rsa.pub里面就是你的公钥复制下来

服务器上root进入/etc/ssh 目录,编辑 sshd_config,打开以下三个配置的注释:

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

/etc/rc.d/init.d/sshd restart //重启ssh
mkdir -p /home/git/.ssh
touch /home/git/.ssh/authorized_keys //新建了信任公钥

然后将客户机们的公钥id_rsa.pub里面的内容复制到git用户的authorized_keys里面

修改权限并创建仓库

在home下建立对应的工程最好,每个用管理自己的工程

sudo git init --bare /home/git/gitdemo.git

一定要修改权限!!!
免密登录也是这个权限,本身就是免密登录ssh传送的文件.
如果权限对的话就不用管

Warning

修改 .ssh 目录的权限为 700
修改 .ssh/authorized_keys 文件的权限为 600
仓库,.ssh目录和authorized_keys都要修改所有者

chmod 700  /home/git/.ssh
chmod 600  /home/git/.ssh/authorized_keys 

chown -R git:git /home/git // 其实这一句就够了
chown -R git:git /home/git/.ssh 
chown -R git:git /home/git/.ssh/authorized_keys 
chown -R git:git /home/git/gitdemo.git  //chown -R 所有者:组

连接远程分支

这时候客户机本地应该可以clone了,url有两种写法(推荐ssh)

git@192.168.0.100:/home/git/gitdemo.git //SCP写法
ssh://git@192.168.0.100/home/git/gitdemo.git //SSH写法
//Https的写法没有配置,而且每次都要输密码,团队协作不好用

如果是本地已经有repo了,可和远程连接起来
git remote add origin git@192.168.0.100:/home/git/gitdemo.git
git push --set-upstream origin main 把本地的main分支和远程main关联起来(假设只有main分支)
pull,merge就可以用来了
冷知识,仓库的语言是server设置的,没用的知识增加了。

工作流参考

gitflow

gitflow工作流,团队开发的范例。

|500

github工作流

600 主要流程为:

  • 新建分支(Create a branch)
  • 提交修改(Add commits)
  • 创建PR(Open a Pull Request)
  • 代码评审(Discuss and review your code)
  • 部署(Deploy)
  • 合并(Merge)

多平台换行符问题(LF or CRLF)

问题[1]

git提示code analyze的时候换行符是否要转换
文本文件所使用的换行符,在不同的系统平台上是不一样的。UNIX/Linux 使用的是 0x0A(LF),早期的 Mac OS 使用的是 0x0D(CR),后来的 OS X 在更换内核后与 UNIX 保持一致了。但 DOS/Windows 一直使用 0x0D0A(CRLF) 作为换行符
在不同平台上,换行符发生改变时,Git 会认为整个文件被修改,这就造成我们没法 diff,不能正确反映本次的修改。

git使用git config --global core.autocrlf true用于在提交和检出时自动转换换行符,选项有三个

  • true提交时转换为LF,检出时转换为CRLF
  • input提交时转换为LF,检出时不转换
  • false提交检出均不转换

git使用 git config --global core.safecrlf true 用于检查文件是否包含混合换行符,该配置也有三个可选项:

  • true 禁止提交混合换行符的文本文件(git add 的时候会被拦截,提示异常)
  • warn 提交混合换行符的文本文件的时候发出警告,但是不会阻止 git add 操作
  • false 不禁止提交混合换行符的文本文件(默认配置)

解决方法

直接无视然后提交,两个属性都设为false不转换不警告,这样会造成换行符混乱,diff可能会失效
一种规范换行符的方式是这样的:
使用 Windows 系统的开发者设置:git config --global core.aurocrlf true
使用 Linux/MacOS 的开发者设置:git config --global core.autocrlf input

temp

git reflog 查看命令历史,以便确定要回到未来的哪个版本

git clone Address 克隆项目
git add (.) 把文件添加到暂存区,未跟踪的文件可以直接添加为跟踪
git restore
git push -u origin master 推送到 远程的master分支
git fetch 从分支获取
git pull 获取分支
git commit -m "你的提交信息"
git checkout (id or -)(/path/file) 回到(某个or上一个)提交点,可以直接用tag名,跟文件名可以直接修改单独某个文件

git remote add Name RemoteAddress.git 添加一个远程仓库地址。

📌Tip

https是无状态的,使用https提交每次都要输入用户名和密码,SSH url克隆需要在克隆之前先配置和添加好SSH key,ssh默认是每次fetch和push代码都不需要输入账号和密码,如果你想要每次都输入账号密码才能进行fetch和push也可以另外进行设置。

git rm --cached 文件名 停止对git已跟踪的文件跟踪,但保留之前该文件的跟踪状态

在一个分支下开发,这种做法是没有问题的。即在 master 分支里,使用如上操作之后,config.js 就从 git 管理中剔除了,但是仍然存在于硬盘上。并不会影响到本地开发环境的正常调试。
如果同时满足以下条件的情况下就会出问题
1 多分支同时存在 config.php 文件。例如,master 分支,dev 分支都有 config.php 文件
2 一个分支删除了该文件,然后在另一个分支,merge 了该提交
这时候dev和master分支的config.js就全消失了。

git update-index --assume-unchanged 文件名 暂时让git忽略已跟踪的文件,具体看这一篇

虽然能达到(暂时的)目的,但并非最正确的做法,这样做是误解了 git update-index 的含义,而且这样做带来的最直接(不良)后果是这样的:

1 所有的团队成员都必须对目标文件执行:git update-index --assume-unchanged PATH。这是因为即使你让 Git 假装看不见目标文件的改变,但文件本身还是在 Git 的历史记录里的,所以团队的每个人在 fetch 的时候都会拉到目标文件的变更。(但实际上目标文件是根本不想被 Git 记录的,而不是假装看不见它发生了改变)

2 一旦有人改变目标文件之后没有 git update-index --assume-unchanged PATH 就直接 push 了,那么接下来所有拉取了最新代码的成员必须重新执行 update-index,否则 Git 又会开始记录目标文件的变化。这一点实际上很常见的,比如说某成员换了机器或者硬盘,重新 clone 了一份代码库,由于目标文件还在 Git 的历史记录里,所以他/她很可能会忘记 update-index。

git update-index --assume-unchanged 的真正用法是这样的:
1 你正在修改一个巨大的文件,你先对其 git update-index --assume-unchanged,这样 Git 暂时不会理睬你对文件做的修改;
2 当你的工作告一段落决定可以提交的时候,重置改标识:
git update-index --no-assume-unchanged,于是 Git 只需要做一次更新,这是完全可以接受的了;
3 提交+推送。

分支和合并

git branch xxx 产生一个新分支,想回到某个点获取分支可以先checkout

  • 产生新分支 git checkout -b xxx
  • 删除分支 git branch -d xxx git merge xxx 将xxx合并到master,出现confilct的时候,大于号小于号和等号之间分别是两个分支不同的内容,最后需要在commit一次
    和mrege的作用是一样的,不过结果不同。

Warning

merge会在head后面紧接着提交,合并后自动提交一次作为标记,worktree会有一个分支记录。
rebase会在分支根提交点处接着提交,之后再跟上master该节点之后的的提交,worktree不会有分支记录。


  1. git多平台换行符问题(LF/CRLF) - Sampwood的One Pieceopen in new window ↩︎

Loading...