手把手教你结合commitizen 搭建属于自己的项目git commit 校验工具

先丢出最终版的index.js文件内容#!/usr/bin/env node"use strict";const path = require(‘path’);const editJsonFile = require(“edit-json-file”);const arg = process.argv// 初始化my-commit ,将部分脚本写入到package.json中if (arg[2] && arg[2] === ‘init’) { // If the file doesn’t exist, the content will be an empty object by default. let file = editJsonFile(${process.cwd()}/package.json); // Set a couple of fields file.set(“husky”, {“hooks”: { “pre-commit”: “lint-staged” }}); file.set(“lint-staged”, { “src/.js”: “[’eslint –fix’]” }); // 询问是否全部使用git add . var List = require(‘prompt-list’); var list = new List({ name: ‘order’, message: ‘是否默认使用git add .’, // choices may be defined as an array or a function that returns an array choices: [ ‘yes’, ’no’ ] }) // async list.ask(function(answer) { file.set(“scripts”, { “my-ci”: answer === ‘yes’ ? ‘git add . && cross-env ./node_modules/.bin/my-commit’ : ‘cross-env ./node_modules/.bin/my-commit’ }); // Output the content file.save(); var shell = require(‘shelljs’); console.log(‘开始安装依赖’); shell.exec(’npm i husky –save-dev’, {async: true}) console.log(‘正在安装 husky—- ‘); shell.exec(’npm i cross-env –save-dev’, {async: true}) console.log(‘正在安装cross-env —- ‘); shell.exec(’npm i lint-staged –save-dev’, {async: true}) })} else { const bootstrap = require(‘commitizen/dist/cli/git-cz’).bootstrap; bootstrap({ cliPath: path.join(__dirname, ‘../../node_modules/commitizen’), // this is new config: { “path”: “cz-conventional-changelog”, “path”: “cz-emoji” } });}步骤一、创建工具项目1.使用git/gitlab创建一个空的仓库2.在空仓库中添加index.js 内容如下// index.js#!/usr/bin/env node"use strict";const bootstrap = require(‘commitizen/dist/cli/git-cz’).bootstrap; bootstrap({ cliPath: path.join(__dirname, ‘../../node_modules/commitizen’), // this is new config: { “path”: “cz-conventional-changelog” } });使用工具到相应的项目(假设插件名称my-commit)1.先发布你的工具项目到npm,相当于创建一个npm包、具体怎么发布 这里不做赘述,网上很多教程2.安装工具(假设插件名称my-commit)npm install my-commit –save-dev3.配置需要在package.json的script中添加如下// my-ci 是自己定义的写成什么都可以"my-ci": “./node_modules/.bin/my-commit"4.配置之后 执行了git add .之后 执行npm run my-ci 将会出现选填补充信息的选项如果觉得git add.之后再执行 npm run my-ci 有点麻烦,可以直接改成// my-ci 是自己定义的写成什么都可以"my-ci”: “git add. && ./node_modules/.bin/my-commit"5 因为以上命令存在不同系统路径不兼容问题 需要加入 cross-envnpm install cross-env –save-dev 6 再次修改package.json// my-ci 是自己定义的写成什么都可以"my-ci”: “git add. && cross-env ./node_modules/.bin/my-commit"当需要提交代码的时候,不用执行git add . 直接执行npm run my-ci即可7 提示信息加上可爱的表情需要在index.js文件中添加 cz-emoji 如下// index.js#!/usr/bin/env node"use strict”;const bootstrap = require(‘commitizen/dist/cli/git-cz’).bootstrap; bootstrap({ cliPath: path.join(__dirname, ‘../../node_modules/commitizen’), // this is new config: { “path”: “cz-conventional-changelog”, “path”: “cz-emoji” } });这个时候 重新发npm包之后再安装到自己的项目下,执行提交的时候8 为了增强校验功能,加入eslint对文件进行这个有点复杂,需要通过lint-staged来判断所以先安装以下依赖npm i husky –save-devnpm i lint-stage –save-dev配置package.json// 增加属性 “husky”: { “hooks”: { “pre-commit”: “lint-staged” } }, “lint-staged”: { “src/.js”: [ “eslint –fix” ] },// 其中src的具体路径是可以自己配置// 校验规则是基于当前目录的.eslintrc.js 文件,如果有些规则不想要,就配置这个文件 这个时候我们提交代码的时候再输入基本的信息之后会执行一个eslint的代码规则 总结以上配置文件 我们需要 安装的库有npm i my-commit –save-devnpm i cross –save-devnpm i husky –save-devnpm i lint-stage –save-dev需要配置package.json属性有 “script”: { … “my-ci”: “git add. && cross-env ./node_modules/.bin/my-commit” }, “husky”: { “hooks”: { “pre-commit”: “lint-staged” } }, “lint-staged”: { “src/.js”: [ “eslint –fix” ] }, 如果每个项目都这么玩。其实有点耗时间,所以我们做了一下自动化 10 初步自动化修改my-commit中的 index.js#!/usr/bin/env node"use strict";const path = require(‘path’);const editJsonFile = require(“edit-json-file”);const arg = process.argv// 初始化my-commit ,将部分脚本写入到package.json中if (arg[2] && arg[2] === ‘init’) { // If the file doesn’t exist, the content will be an empty object by default. let file = editJsonFile(${process.cwd()}/package.json); // Set a couple of fields file.set(“husky”, {“hooks”: { “pre-commit”: “lint-staged” }}); file.set(“lint-staged”, { “src/.js”: “[’eslint –fix’]” }); // 询问是否全部使用git add . var List = require(‘prompt-list’); var list = new List({ name: ‘order’, message: ‘是否默认使用git add .’, // choices may be defined as an array or a function that returns an array choices: [ ‘yes’, ’no’ ] }) // async list.ask(function(answer) { file.set(“scripts”, { “my-ci”: answer === ‘yes’ ? ‘git add . && cross-env ./node_modules/.bin/my-commit’ : ‘cross-env ./node_modules/.bin/my-commit’ }); // Output the content file.save(); var shell = require(‘shelljs’); console.log(‘开始安装依赖’); shell.exec(’npm i husky –save-dev’, {async: true}) console.log(‘正在安装 husky—- ‘); shell.exec(’npm i cross-env –save-dev’, {async: true}) console.log(‘正在安装cross-env —- ‘); shell.exec(’npm i lint-staged –save-dev’, {async: true}) })} else { const bootstrap = require(‘commitizen/dist/cli/git-cz’).bootstrap; bootstrap({ cliPath: path.join(__dirname, ‘../../node_modules/commitizen’), // this is new config: { “path”: “cz-conventional-changelog”, “path”: “cz-emoji” } });} 清除掉以前配置的package.json只要两部安装即可npm i my-commitnpx my-commit init提交代码的时候直接执行 npm run my-ci 即可11 更智能(摸索中) ...

October 23, 2018 · 3 min · jiezi

iOS开发手册

1.工程文件结构所有的文件应放在工程中的项目目录下。项目文件和物理文件需保持一致。Xcode创建的任何组(group)都必须在文件系统中有映射。项目文件不仅可以按照业务类型分组,也可以根据功能分组。2.代码格式规范2.1 代码注释格式文件注释:采用Xcode自动生成的注释格式。//// AppDelegate.h// 项目名称//// Created by 开发者姓名 on 2018/6/8.// Copyright © 2018年 公司名称. All rights reserved.//import注释:如果有一个以上的import语句,对这些语句进行分组,每个分组的注释是可选的。// Framework#import <UIKit/UIKit.h>// Model#import “WTUser.h”// View#import “WTView.h"方法注释:Xcode8之后快捷键自动生成(option + command + /)。/**<#Description#>@param application <#application description#>@param launchOptions <#launchOptions description#>@return <#return value description#>*/- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;代码块注释:单行的用 “// + 空格” 开头, 多行用“/ /”。2.2 代码结构与排版声明文件:方法顺序和实现文件的顺序保持一致,根据需要用”#pragma mark -“将方法分组。实现文件:必须用”#pragma mark -“将方法分组。分组前后优先级:Lifecycle方法 > Public方法 > UI方法 > Data方法 > Event方法 > Private方法(逻辑处理等) > Delegate方法 > 部分Override方法 > Setter方法 > Getter方法。#pragma mark - Lifecycle- (instancetype)init {}- (void)viewDidLoad {}- (void)viewWillAppear:(BOOL)animated {}- (void)viewDidAppear:(BOOL)animated {}- (void)viewWillDisappear:(BOOL)animated {}- (void)viewDidDisappear:(BOOL)animated {}- (void)didReceiveMemoryWarning {}- (void)dealloc {}#pragma mark - Public- (void)refreshData {}#pragma mark - UI- (void)initSubViews {}#pragma mark - Data- (void)initData {}- (void)constructData {}#pragma mark - Event- (void)clickButton:(UIButton *)button {}#pragma mark - Private- (CGFloat)calculateHeight {}#pragma mark - UIScrollViewDelegate- (void)scrollViewDidScroll:(UIScrollView *)scrollView {}#pragma mark - Override- (BOOL)needNavigationBar {}#pragma mark - Setter- (void)setWindow:(UIWindow *)window {}#pragma mark - Getter- (UIWindow *)window {}变量:优先使用属性声明而非变量声明,注意属性修饰符、变量类型、变量之间的间隔。@property (strong, nonatomic) UIWindow *window;点语法:应始终使用点语法来访问和修改属性。间距要求如下:一个缩进使用四个空格。在”-“或者”+“号之后应该有一个空格,方法的大括号和其它大括号始终和声明在同一行开始,在新的一行结束,另外方法之间应该空一行。- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary )launchOptions { if (door.isClosed) { // Do something } else { // Do something } return YES;}长度要求如下:每行代码的长度不应该超过100个字符。单个函数或方法的实现代码控制在50行以内。单个文件里的代码行数控制在500600行之内。3.代码命名规范3.1 代码命名基础最好是既清晰又简短,但不要为简短丧失清晰性,并使用驼峰命名法。名称通常不缩写,即使名称很长也要拼写完全(禁止拼音),然而可使用少数非常常见的缩写,部分举例如下:常用缩写词含义常用缩写词含义appapplicationmaxmaximumaltalternateminminimumcalccalculatemsgmessageallocallocterectrectangledeallocdealloctemsgmessageinitinitializetemptemporaryintintegerfuncfunction由于Cocoa(Objective-C)没有C++一样的命名空间机制,需添加前缀(公司名首字母)防止命名冲突,前缀使用2个字符(以下统称项目前缀)。常见的单词略写:ASCII,PDF,HTTP,XML,URL,JPG,GIF,PNG,RGB等3.2 类和协议命名类名应明确该类的功能,并且要有项目前缀防止命名冲突。协议组合一组方法作为一个类的部分接口使用, 用类名作为协议名,例如:NSObject。协议仅仅组合一组方法而不关联具体类,这种协议的命名应采用动名词形式(ing)。委托形式的协议命名为类名加上Delegate,例如:UIScrollViewDelegate。3.3 变量和属性命名变量名应前置下划线“”,属性名没有下划线。属性本质上是存取方法setter/getter,可进行重写(注意内存管理)。@property (strong, nonatomic) UIWindow *window;- (void)setWindow:(UIWindow *)window;- (UIWindow *)window;可以适当的对setter/getter进行别名设置。@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled;3.4 方法和函数命名方法名和函数名一般不需要前缀,但函数(C语言形式)作为全局作用域的时候最好加上项目前缀。 表示行为的方法名称以动词开头,但不要使用do/does等无实际意义的助动词。参数前面的单词要能够描述该参数,并且参数名最好能用描述该参数的单词命名。- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;方法中多个参数可以使用适当的介词进行连接。// 后续多个参数使用with- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;// 添加适当介词能够使方法的含义更明确- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;// 第一个参数用了with,后面的参数不使用with- (instancetype)initWithImage:(nullable UIImage *)image highlightedImage:(nullable UIImage *)highlightedImage;只有在方法返回多个值的时候使用get单词进行明确。- (void)getLineDash:(nullable CGFloat *)pattern count:(nullable NSInteger *)count phase:(nullable CGFloat *)phase;方法返回某个对象实例。// 类方法创建对象+ (instancetype)buttonWithType:(UIButtonType)buttonType;// 单例命名+ (UIApplication *)sharedApplication; 委托或代理方法命名第一个参数最好能相关某个对象。- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;私有方法不要以下划线““开头,因为系统私有方法保留此方式。自定义方法和系统方法重名,建议在方法开头加前缀”xx_methodName“。3.5 常量和宏的命名const常量外部声明:在Objective-C文件中优先采用FOUNDATION_EXTERN和UIKIT_EXTERN,而非C语言中的extern。const常量采用驼峰命名原则。const常量根据作用域适当加上前缀(含项目前缀):可供外部使用需加上相应的类名或者模块前缀,仅文件内部使用需要加上小写字母“k”.宏定义每个字母采用大写,单词之间用下划线“”间隔。宏定义也可根据作用范围加上适当前缀,避免命名冲突。3.6 枚举的命名使用枚举来定义一组相关的整数常量,增强代码的可读性。枚举可根据作用域添加前缀(含项目前缀),格式:[相关类名或功能模块名] + [描述] + [状态]。建议优先采用Objective-C的声明NS_ENUM和NS_OPTIONS,少采用C语言形式的enum等枚举声明.枚举定义时需指定None状态,并且其rawValue一般为起始值0。// NS_ENUMtypedef NS_ENUM(NSInteger, UIStatusBarAnimation) { UIStatusBarAnimationNone = 0, UIStatusBarAnimationFade = 1, UIStatusBarAnimationSlide = 2,}typedef NS_OPTIONS(NSUInteger, UIRemoteNotificationType) { UIRemoteNotificationTypeNone = 0, UIRemoteNotificationTypeBadge = 1 << 0, UIRemoteNotificationTypeSound = 1 << 1, UIRemoteNotificationTypeAlert = 1 << 2, UIRemoteNotificationTypeNewsstandContentAvailability = 1 << 3,}3.7 通知命名外部声明:在Objective-C文件中优先采用FOUNDATION_EXTERN和UIKIT_EXTERN,而非C语言中的extern。通知的命名一般都是跨文件使用的,需添加项目前缀。// [相关联类名或者功能模块名] + [will/Did](可选) + [描述] + NotificationUIApplicationDidEnterBackgroundNotification UIApplicationWillEnterForegroundNotification 3.8 类型别名命名根据作用域添加前缀(含项目前缀),格式:[类名或功能模块名] + [描述]。4.文件资源命名规范资源文件命名也需加上项目前缀。资源文件名全小写,单词之间用下划线“”间隔。资源文件命名格式:[项目前缀] + [业务] + [文件名]图片文件命名格式:[项目前缀] + [业务] + [类型] + [状态]。// 常见类型:logol,icon,img// 常见状态:normal,selected,highlightUIImage *image = [UIImage imageNamed:@“wt_setting_icon_normal”];5.代码警告处理注意警告问题的隐蔽性,因此最好修复警告。警告类型的查看步骤:选中警告 -> 右键Reveal in Log(不编译Reveal in Log是灰色的,因此先编译) ->查看方括号的内容如果需要忽略警告,建议优先代码push或者pop处理。#pragma clang diagnostic push#pragma clang diagnostic ignored “-Warc-retain-cycles”// 造成警告的代码#pragma clang diagnostic pop如果警告数量过大,检查警告类型以及必要性,可xcode配置忽略此类型警告。步骤:选中工程 -> TARGETS -> Build Settings -> Other Warning Flags。忽略单个和全局配置稍有差别,如下举例:push/pop Other Warning Flags-Wformat —-> -Wno-format -Wunused-variable —-> -Wno-unused-variable -Wundeclared-selector —-> -Wno-undeclared-selector -Wint-conversion —-> -Wno-int-conversion也可以在pch等大范围作用域的头文件中添加代码来忽略后续警告:#pragma clang diagnostic ignored “警告名称” 。6.外部库文件引入库文件引入最好把警告处理掉。库文件引入优先采用CocoaPods引入,并且指定版本号。源文件方式需引入文件到工程目录下。源文件方式需注意有无版本说明信息(可能在README文件中,也可能在某个.h头文件中,又或者有Version文件)没有时需在库文件目录下新增版本说明文件,7.代码版本管理版本管理工具:svn 或 git。svn文件管理配置:目录/.subversion打开config文件配置global-ignore。git文件管理配置:.gitignore文件记录了被git忽略的文件,作用于本仓库,常见语法如下:井号(#)用来添加注释用的,比如 “#注释”。build/ : 星号()是通配符,build/则是要说明要忽略 build 文件夹下的所有内容。.pbxuser : 表示要忽略后缀名为.pbxuser的文件。!default.pbxuser : 感叹号(!)是取反的意思,.pbxuser 表示忽略所有后缀名为.pbxuser的文件,如果加上!default.pbxuser则表示,除了default.pbxuse忽略其它后缀名为pbxuse的文件。提交信息规范:BUG类型为“Fix + [BUG编号] + [BUG描述]”。任务类型为“Done + [任务编号] + [任务描述]”。任务中间态为“Doing + [任务编号] + [任务描述]”。引入类库为“import + [类库名]”。8.构建和分发手动构建:Xcode界面化构建注、xcodebuild终端命令构建。自动化构建:Jenkins+Fastlane、xcodebuild脚本执行 。内测分发渠道:fir.im、蒲公英等。线上分发渠道:AppStore。 ...

October 23, 2018 · 2 min · jiezi

Git的奇技淫巧

此文果断收藏 Git是一个“分布式版本管理工具”,简单的理解版本管理工具:大家在写东西的时候都用过“回撤”这个功能,但是回撤只能回撤几步,假如想要找回我三天之前的修改,光用“回撤”是找不回来的。而“版本管理工具”能记录每次的修改,只要提交到版本仓库,你就可以找到之前任何时刻的状态(文本状态)。下面的内容就是列举了常用的Git命令和一些小技巧,可以通过"页面内查找"的方式进行快速查询:Ctrl/Command+f。开卷必读一定要先测试命令的效果后,再用于工作环境中,以防造成不能弥补的后果!到时候别拿着砍刀来找我所有的命令都在git version 2.7.4 (Apple Git-66)下测试通过统一概念:工作区:改动(增删文件和内容)暂存区:输入命令:git add 改动的文件名,此次改动就放到了‘暂存区’本地仓库(简称:本地):输入命令:git commit 此次修改的描述,此次改动就放到了’本地仓库’,每个commit,我叫它为一个‘版本’。远程仓库(简称:远程):输入命令:git push 远程仓库,此次改动就放到了‘远程仓库’(GitHub等)commit-id:输出命令:git log,最上面那行commit xxxxxx,后面的字符串就是commit-id目录展示帮助信息回到远程仓库的状态重设第一个commit展示工作区和暂存区的不同展示暂存区和最近版本的不同展示暂存区、工作区和最近版本的不同快速切换分支删除已经合并到master的分支展示本地分支关联远程仓库的情况关联远程分支列出所有远程分支列出本地和远程分支创建并切换到本地分支创建并切换到远程分支删除本地分支删除远程分支重命名本地分支查看标签本地创建标签推送标签到远程仓库删除本地标签删除远程标签切回到某个标签放弃工作区的修改恢复删除的文件以新增一个commit的方式还原某一个commit的修改回到某个commit的状态,并删除后面的commit修改上一个commit的描述查看commit历史显示本地更新过HEAD的git命令记录修改作者名修改远程仓库的url增加远程仓库列出所有远程仓库查看两个星期内的改动把A分支的某一个commit,放到B分支上给git命令起别名存储当前的修改,但不用提交commit保存当前状态,包括untracked的文件展示所有stashes回到某个stash的状态回到最后一个stash的状态,并删除这个stash删除所有的stash从stash中拿出某个文件的修改展示所有tracked的文件展示所有untracked的文件展示所有忽略的文件强制删除untracked的文件强制删除untracked的目录展示简化的commit历史查看某段代码是谁写的把某一个分支到导出成一个文件从包中导入分支执行rebase之前自动stash从远程仓库根据ID,拉下某一状态,到本地分支详细展示一行中的修改清除.gitignore文件中记录的文件展示所有alias和configs展示忽略的文件commit历史中显示Branch1有的,但是Branch2没有commit在commit log中显示GPG签名删除全局设置新建并切换到新分支上,同时这个分支没有任何commit展示任意分支某一文件的内容clone下来指定的单一分支忽略某个文件的改动忽略文件的权限变化以最后提交的顺序列出所有Git分支在commit log中查找相关内容把暂存区的指定file放到工作区中强制推送联系我展示帮助信息git help -g回到远程仓库的状态抛弃本地所有的修改,回到远程仓库的状态。git fetch –all && git reset –hard origin/master重设第一个commit也就是把所有的改动都重新放回工作区,并清空所有的commit,这样就可以重新提交第一个commit了git update-ref -d HEAD展示工作区和暂存区的不同输出工作区和暂存区的different(不同)。git diff还可以展示本地仓库中任意两个commit之间的文件变动:git diff <commit-id> <commit-id>展示暂存区和最近版本的不同输出暂存区和本地最近的版本(commit)的different(不同)。git diff –cached展示暂存区、工作区和最近版本的不同输出工作区、暂存区 和本地最近的版本(commit)的different(不同)。git diff HEAD快速切换分支git checkout -删除已经合并到master的分支git branch –merged master | grep -v ‘^*| master’ | xargs -n 1 git branch -d展示本地分支关联远程仓库的情况git branch -vv关联远程分支关联之后,git branch -vv就可以展示关联的远程分支名了,同时推送到远程仓库直接:git push,不需要指定远程仓库了。git branch -u origin/mybranch或者在push时加上-u参数git push origin/mybranch -u列出所有远程分支-r参数相当于:remotegit branch -r列出本地和远程分支-a参数相当于:allgit branch -a创建并切换到本地分支git checkout -b <branch-name>创建并切换到远程分支git checkout -b <branch-name> origin/<branch-name>删除本地分支git branch -d <local-branchname>删除远程分支git push origin –delete <remote-branchname>或者git push origin :<remote-branchname>重命名本地分支git branch -m <new-branch-name>查看标签git tag展示当前分支的最近的taggit describe –tags –abbrev=0本地创建标签git tag <version-number>默认tag是打在最近的一次commit上,如果需要指定commit打tag:$ git tag -a <version-number> -m “v1.0 发布(描述)” <commit-id>推送标签到远程仓库首先要保证本地创建好了标签才可以推送标签到远程仓库:git push origin <local-version-number>一次性推送所有标签,同步到远程仓库:git push origin –tags删除本地标签git tag -d <tag-name>删除远程标签删除远程标签需要先删除本地标签,再执行下面的命令:git push origin :refs/tags/<tag-name>切回到某个标签一般上线之前都会打tag,就是为了防止上线后出现问题,方便快速回退到上一版本。下面的命令是回到某一标签下的状态:git checkout -b branch_name tag_name放弃工作区的修改git checkout <file-name>放弃所有修改:git checkout .恢复删除的文件git rev-list -n 1 HEAD – <file_path> #得到 deleting_commitgit checkout <deleting_commit>^ – <file_path> #回到删除文件 deleting_commit 之前的状态以新增一个commit的方式还原某一个commit的修改git revert <commit-id>回到某个commit的状态,并删除后面的commit和revert的区别:reset命令会抹去某个commit id之后的所有commitgit reset <commit-id> #默认就是-mixed参数。git reset –mixed HEAD^ #回退至上个版本,它将重置HEAD到另外一个commit,并且重置暂存区以便和HEAD相匹配,但是也到此为止。工作区不会被更改。git reset –soft HEAD~3 #回退至三个版本之前,只回退了commit的信息,暂存区和工作区与回退之前保持一致。如果还要提交,直接commit即可 git reset –hard <commit-id> #彻底回退到指定commit-id的状态,暂存区和工作区也会变为指定commit-id版本的内容修改上一个commit的描述git commit –amend查看commit历史git log查看某段代码是谁写的blame的意思为‘责怪’,你懂的。git blame <file-name>显示本地更新过HEAD的git命令记录每次更新了HEAD 的git 命令比如 commint、amend、cherry-pick、reset、revert等都会被记录下来(不限分支),就像shell的history一样。这样你可以reset 到任何一次更新了HEAD 的操作之后,而不仅仅是回到当前分支下的某个commit 之后的状态。git reflog修改作者名git commit –amend –author=‘Author Name <email@address.com>‘修改远程仓库的urlgit remote set-url origin <URL>增加远程仓库git remote add origin <remote-url>列出所有远程仓库git remote查看两个星期内的改动git whatchanged –since=‘2 weeks ago’把A分支的某一个commit,放到B分支上这个过程需要cherry-pick命令,参考git checkout <branch-name> && git cherry-pick <commit-id>给git命令起别名简化命令git config –global alias.<handle> <command>比如:git status 改成 git st,这样可以简化命令git config –global alias.st status存储当前的修改,但不用提交commit详解可以参考廖雪峰老师的git教程git stash保存当前状态,包括untracked的文件untracked文件:新建的文件git stash -u展示所有stashesgit stash list回到某个stash的状态git stash apply <stash@{n}>回到最后一个stash的状态,并删除这个stashgit stash pop删除所有的stashgit stash clear从stash中拿出某个文件的修改git checkout <stash@{n}> – <file-path>展示所有tracked的文件git ls-files -t展示所有untracked的文件git ls-files –others展示所有忽略的文件git ls-files –others -i –exclude-standard强制删除untracked的文件可以用来删除新建的文件。如果不指定文件文件名,则清空所有工作的untracked文件。clean命令,注意两点:clean后,删除的文件无法找回不会影响tracked的文件的改动,只会删除untracked的文件git clean <file-name> -f强制删除untracked的目录可以用来删除新建的目录,注意:这个命令也可以用来删除untracked的文件。详情见上一条git clean <directory-name> -df展示简化的commit历史git log –pretty=oneline –graph –decorate –all把某一个分支到导出成一个文件git bundle create <file> <branch-name>从包中导入分支新建一个分支,分支内容就是上面git bundle create命令导出的内容git clone repo.bundle <repo-dir> -b <branch-name>执行rebase之前自动stashgit rebase –autostash从远程仓库根据ID,拉下某一状态,到本地分支git fetch origin pull/<id>/head:<branch-name>详细展示一行中的修改git diff –word-diff清除gitignore文件中记录的文件git clean -X -f展示所有alias和configs注意: config分为:当前目录(local)和全局(golbal)的config,默认为当前目录的configgit config –local –list (当前目录)git config –global –list (全局)展示忽略的文件git status –ignoredcommit历史中显示Branch1有的,但是Branch2没有commitgit log Branch1 ^Branch2在commit log中显示GPG签名git log –show-signature删除全局设置git config –global –unset <entry-name>新建并切换到新分支上,同时这个分支没有任何commit相当于保存修改,但是重写commit历史git checkout –orphan <branch-name>展示任意分支某一文件的内容git show <branch-name>:<file-name>clone下来指定的单一分支git clone -b <branch-name> –single-branch https://github.com/user/repo.git忽略某个文件的改动关闭 track 指定文件的改动,也就是 Git 将不会在记录这个文件的改动git update-index –assume-unchanged path/to/file恢复 track 指定文件的改动git update-index –no-assume-unchanged path/to/file忽略文件的权限变化不再将文件的权限变化视作改动git config core.fileMode false以最后提交的顺序列出所有Git分支最新的放在最上面git for-each-ref –sort=-committerdate –format=’%(refname:short)’ refs/heads/在commit log中查找相关内容通过grep查找,given-text:所需要查找的字段git log –all –grep=’<given-text>‘把暂存区的指定file放到工作区中不添加参数,默认是-mixedgit reset <file-name>强制推送git push -f <remote-name> <branch-name>⬆ 返回顶部长按关注订阅号长按进入RDhub群 ...

October 19, 2018 · 2 min · jiezi

git 详解及实用指南之一 (本地操作)

后续会持续更新1.设置开发者的个人信息在任何一个系统之中都会存在有多个开发者(多人协作开发),而在 GIT 之中,对于每一个开发者(电脑),都需要 开发者自己定义自己的名字与 email 地址,以便进行方便的联系,此时需要配置全局信息。配置全局用户名及 email 地址git config –global user.name ‘wzy’git config –global user.email ‘449245884@.com’设置完成之后如果成功不会任何提示信息,可以通过如下命令查看全局配置信息:git config -l可以发现除了之前配置的用户名和 email 地址之外,还存在有其它的内容。2.创建仓库版本库 = 仓库;在此仓库中的所有内容都会被git 管理;在仓库中的所有文件修改、删除、更新都会被纪录下来;可以随时恢复到某一特定状态;初始化仓库: git init如果要开发项目,那么首先必须有一个仓库(可以简单的理解为是一个磁盘上的文件夹)。mkdir myrpo此时 mypro 文件夹是一个空的文件夹,没有任何的内容,只是一个纯粹的目录。将 mypro 文件夹定义为仓库, 进入文件夹, 初始化仓库(将此目录变为可以被GIT管理的仓库) 而且此时会提示,在 mypro 文件夹之中创建了一个“.git”的目录,这个目录就是仓库信息,死都不能改。3.添加文件现在仓库创建完成之后,下面就要进行文件的基本管理了。首先在编写之前有一个说明:所有的文件一定要使用 UTF-8 编码,否则有可能会出现问题。建立一个 Hello.js文件btn.onclick = function() { console.log(‘每一次新增!’);}察看当前仓库的状态git status在 “git status” 状态查询操作上可以发展有如下的几个提示信息:现在开发的属于主分支:On branch master初始化仓库的提交:No commits yet未标记的文件:Untracked files:随后给出的一些操作的命令:(use “git add <file>…” to include in what will be committed)未标记文件的列表,现在只有一个: hello.js添加文件到仓库增加文件到暂存区: git add 文件名称提交文件: git commit -m “注释"将文件加入到暂存库之中git add hello.js 继续查询状态此时有了一个最重要的信息:现在的文件并没有真正的提交到主分支上(主分支就是我们真正要运行的程序的所有的代码)。注意:所有修改的代码都会被 GIT 自动的监测到,所有的代码在使用 commit 提交之前一定要先使用 add 增加进来,否则不会有任何的提交。如果现在不希望分两步进行则可以在运行以下程序时增加一个“-a”的参数,表示先 add 而后 commit(git commit -a -m “注释”)。提交文件信息git commit -m “New Js file - Hello.js Create"在进行每次更新提交的时候一般都会为其增加上一些注释数据,所以使用“-m”参数来进行注释的编写。 此时这个“Hello.js”文件就被真正的提交到了主分支上,也就是意味着程序发布成功了。查询状态此时的状态会提示:没有任何的信息需要被提交,工作目录很干净。而在 git 工具下用户每一次进行的提交实际上都 会被日志纪录下来。 察看针对于“hello.js”文件的日志信息首先会出现一个提交的信息号 “2e3e7018a965673a4154c84105b5d1a23f13167a”,可以理解为是每一次提交的 id 号。如果有多次提交,那么这个日志信息也会越来越多。4.修改仓库文件上面代码已经可以成功的进行了发布,但是代码出现就是为了修改。于是现在来观察对于 git 工具如何去控制修改。修改 hello.js 文件btn.onclick = function() { console.log(‘每一次新增!’); console.log(‘第一次修改·!’);}此时发现文件增加了一行的修改。查询一下当前的仓库状态现在 GIT 直接提示用户,文件没有保存到暂存区之中,而且提示有:要么你选择文件暂存,要么你直接进行文件的 恢复,同时给出了已经修改的文件“hello.js”。察看文件的前后区别git diff hello.js 现在可以发现所有增加的内容都会使用“+”表示,而被删除的信息都会使用“-”表示。将修改后的代码加入到暂存区后进行提交git commit -a -m “Update hello.js file. Add one lines"察看修改日志git log hello.js 通过以上的代码演示,现在可以清楚的发现,只要是修改的操作 GIT 都可以进行及时的跟踪。5. 工作区与暂存区工作区与仓库工作区: 就是当前电脑的操作目录(包含 .git);仓库:工作区有一个隐藏目录 .git,这个不算工作区,而是 git 的仓库,git 版本库里保存了很多东西,其中最重要的就是称为 stage 的暂存区,还有 git 为用户自动创建的主程序分支 master ,以及指向 master 的 head 指针。概念解释:在之前所编写的“hello.js”文件保存在用户工作区之中;当使用 add 命令之后,实际上就是将所有的文件提交到暂存区(state) 之中;使用 commit 命令之后,才表示真正的发出了修改,而真正可以运行的程序都保存在 master 分支上;6. 工作区上的操作修改 Hello.jsbtn.onclick = function() { console.log(‘第二次修改·!’);}增加一个 demo.js 文件btn2.onclick = function() { console.log(‘demo click’);}现在的工作区中的代码已经发生了变化。用 status 跟踪现在会提示有以下信息:修改了 Hello.js 文件,而这个文件给出了处理方式;出现了一个未标记的文件(Demo.js),询问用户是否将其加入到暂存区之中。7. 缓存区上的操作使用“git add”将代码添加到暂存区之中git add .本次操作使用了一个“.”,那么就表示全部加入。修改之后再次观察状态。观察状态 8. 提交修改数据保存在暂存区之后,下面就要进行代码的提交,将代码提交到主分支上。 当把暂存区的代码提交到主分支上之后,会自动的清空暂存区之中的内容。提交修改代码git commit -m ‘add demo.js file’那么此时再次查询状态。那么会直接发现没有任何的文件修改的提示。9. 版本回退每当用户进行代码提交的时候都会自动的生成一个 commit id,而这个 commit id 就是进行代码回退的主要操作方式。查询当前修改后的日志信息git log –pretty=oneline大家可以发现所有的 commit id 并不是顺序的 1、2、3 编号,而是由系统生成一个十六进制数据,这一概念就跟 Session ID 类似,由 GIT 自己控制,主要是为了防止版本号的冲突。在 master 分之上会有一个 HEAD 指针存在,而这个指针默认情况下永远指向最后一次提交的位置。当使用回退之后发现 HEAD 指针出现了改变,如果回退一步,那么之前的操作不会被删除,但是所有的代码将回归到指定位置的状态。**回退一步git reset –hard HEAD~1那么如果说现在还想恢复最新的状态呢?那么就必须找到回退的 commit id。找到所有的已经删除的信息 commitidgit reflog恢复最后一次提交 git reset –hard cc54c43 10.提示:文件修改问题在有了暂存区和 master 主分支概念之后,就需要回避一个问题:只有保存在暂存区之中的内容才可以被真正的修改, 而不是针对于文件。编写 hello.js 文件btn.onclick = function() { console.log(‘我的小智’);}以上是 =hello.js 文件的第一次修改。 将修改的文件增加到暂存区之中git add.此时并没有提交,而后再次修改 hello.js 文件。 btn.onclick = function() { console.log(‘我的王大冶’); }但是这个时候此文件并没有使用 add 进行加入。进行提交(提交的时候只提交暂存区的内容)git commit -m “change print” 可是这个时候只是提交了第一次修改,而第二次修改并没有提交。查询状态进行对比git diff HEAD hello.js HEAD 是指向最后一次提交的指针,现在的含义是将 HEAD 中的 Hello.java 文件与工作区的 Hello.java 文件进行对比。总结:如果一个文件修改多次了,那么就需要执行多次的 add 后才可以提交,否则在 add 前的修改是不会被提交的。11. 撤消修改情况一:在未增加(git add) 与提交前(git commit) 用户可以直接撤消对文件做出的修改操作。撤消所做出的修改操作: git checkout – 文件名情况二:在已增加(git add)与未提交前(git commit) 用户可以直接撤消对文件所做出的修改操作。撤消暂存区的修改操作:git reset HEAD 文件名称;丢掉已经修改的文件内容: git checkout – 文件名称;情况一:未增加(git add)&提交(git commit)如果在工作区之中的代码并没有增加到暂存区之中,那么如果要恢复到原始状态是很容易的。现在假设修改了 hello.js btn.onclick = function() { console.log(‘我的王大冶’);}就是要改代码,不干走人了,老子不吃你这套但是只要是文件一修改,那么 git 就可以立即跟踪到状态。但是后来发现,此种修改实在是不应该进行,如果进行了,只能有一个结论:此人脑袋有问题。但是写代码的时候 可能不知道上一次修改状态。恢复git checkout – hello.js执行之后发现 Hello.java 文件就恢复到了一个原始的状态(上一次的提交状态)。情况二:已增加( git add )& 未提交( git commit )现在假设要修改的文件已经提交到了暂存区之中。将 Hello.java 代码提交到暂存区中git add.当查询状态时:在状态查询的时候已经给出了用户的提示,即:你可以根据 HEAD 指针来恢复文件。从暂存区之中退出git reset HEAD hello.js 于是再次查询状态相当于现在已经由暂存区中保存的内容恢复到了工作区,那么既然在工作区了,就可以直接恢复原始状态。恢复原始git checkout – hello.js 个人建议:养成良好的开发习惯,别像演示那样这么对待代码。12. 删除文件现在在仓库之中存在有 Demo.js 文件,但是假设这个文件从此之后不再使用了呢?只有一个解决方案:删除。但是 在 GIT 里面对于删除文件这一功能严格来讲也属于一个修改操作。从磁盘上删除 Demo.js 文件 rm demo.js 当文件删除之后下面查询状态; 这个时候文件是从当前工作区的磁盘中删除了,同时也提示文件被删除。提交更新git commit -a -m “Delete Demo.java File"但是如果说发现文件被删除错误了呢?则应该进行恢复。恢复文件git reset –hard bc8e842247b3d78 如果文件被删除,则只能够利用版本控制的方式进行恢复。以上主要对总结于李兴华老师的课程,大家有兴趣可以去网易去上观看一个笨笨的码农,我的世界只能终身学习! ...

October 18, 2018 · 2 min · jiezi

Git 常用命令清单,掌握这些,轻松驾驭版本管理

GitHub 地址,欢迎star,查看更多整理的前端知识点工程下载、分支的增删查改工程下载:clone 远程工程:git clone https://XXXX.gitfetch 远程分支到本地某分支:git fetch origin <orginname>:<localname>分支的增删查改查看分支:git branch查看远程所有分支:git branch -r查看本地和远程所有分支:git branch -a创建分支:git branch <name>切换分支:git checkout <name>创建并切换分支:git checkout -b <name>合并某分支到当前分支:git merge <name>把分支推送到远程:git push origin <name>删除本地分支:git branch (-d | -D) <name>删除远程分支:git push origin -d <name>分支重命名:git branch (-m | -M) <oldbranch> <newbranch>注意: 不能删除当前所在本地分支。查看提交信息日志查看分支最近一次的修改列表:git status查看分支的commit信息(倒叙排列)git log 查看commit id, Author, Date, commit infogit shortlog 按提交者分类显示提交信息git log –oneline 只输出commit id 和 commit infogit log –stat 查看增删查改了哪些文件版本回退回退到上一版本:git reset –hard HEAD^回退到上上版本:git reset –hard HEAD^^回退到上上版本:git reset –hard HEAD~2回退到某个版本:git reset –hard <commit id>强制推送到远程分支:git push -f注意: 1、HEAD 指向的版本是当前版本,^ 表示上一个版本,~N 表示上N个版本,<commit id>可简写 2、git log 可以查看<commit id> 3、git reflog 可以查看命令历史,用来回到某个未来的版本文件的添加、提交、拉取、推送、比对、合并添加新增文件:git add README.md添加所有新增文件:git add .暂存变更文件:git stash [save “暂存备注”]恢复暂存文件:git stash pop提交变更文件:git commit -m “变更备注"拉取远程代码:git pull [origin <name>]推送到远程:git push origin <name>比对两个分支:git diff <name1> <name2>比对两个分支变更的文件列表:git diff <name1> <name2> –stat比对本地和远程分支:git diff <name> origin/<name>合并某个分支:git merge <name>强制覆盖本地分支: 1、git fetch –all 2、git reset –hard origin/<name> 3、git pull常用选项和其他命令git 中部分选项解释-f –force:强制-d –delete:删除-D –delete –force-m –move:移动或重命名-M –move –force-r –remote:远程-a –all:所有其他命令清空工程:$ git rm -rf .每隔X秒运行一次git pull:$ for((i=1;i<=10000;i+=1)); do sleep X && git pull; done使用git rebase将一个feature分支变基到master分支$ git checkout feature $ git rebase master配置相关查看当前配置: git config –list修改 git 的 name 和 email :git config –global user.name <name>git config –global user.email <email>提示: Windows 用户可以把配置信息写入.bat文件 ...

October 15, 2018 · 1 min · jiezi

Git 学习笔记

最近公司的代码管理工具要从SVN转到Git上,因此虽然之前用过Git,但是都是一些简单的推送提交,因此还是有必要进行一些系统的学习,这里做一下笔记,以备后询,且不定期更新。关于SVN和Git的比较已经有很多文章说过了,就不再赘述,本文的重点是如何使用常用的Git命令进行操作,冷门的就不说了,且比较零散,系统的学习推介廖雪峰的Git教程。声明下面用户名都为SHERlocked93,请自行修改成自己的用户名1. 概览工作区 Workspace暂存区 Stage / Index本地仓库 Repository远程仓库 Remote2. 修改2.1 暂存修改操作一览操作bash创建stashgit stash查看git stash list应用git stash apply stash@{<num>}删除git stash drop stash@{<num>}还原上一个暂存并删除暂存(如无conflict)git stash pop如果在工作的时候出现了临时需要解决的问题,而你又不希望提交,那么有个stash功能git stash在暂存后工作区会回退到最近的一个commit的状态,以便开建新分支;比如我们修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。2.2 撤销修改还未提交到暂存区当修改还没有被add的时候,可以使用git checkout – filename.txt来丢弃工作区某文件的修改,当然也可以把后面的文件改成*来撤销所有文件的修改。这是用仓库的文件覆盖工作区的文件。注意这里用的是–,如果没有这个–的话就变成切换分支了。还未提交到仓库如果你的修改已经被add到了暂存区,但是还没有被commit,那么可以使用git reset HEAD filename.txtgit checkout – filename.txt首先用reset来把修改撤回到工作区,再使用上面的checkout命令撤回工作区的修改。这里的reset相当于add的反操作。已经提交到仓库则可以版本回退git reset –hard 15zdx2s这里的–hard表示强制回退,丢弃本地的修改。这个回退比较野蛮,该版本号之后的提交都将不可见。撤销之前某一个提交git revert撤销一个提交的同时会创建一个新的提交,这是一个安全的方法,因为它不会重写提交历史。但实现上和reset是完全不同的。它撤销这个提交引入的更改,然后在最后加上一个撤销了更改的新提交,而不是从项目历史中移除这个提交。git revert 46af7z6相较于reset ,revert不会改变项目历史,对那些已经发布到共享仓库的提交来说这是一个安全的操作。其次git revert 可以将提交历史中的任何一个提交撤销、而reset会把历史上某个提交及之后所有的提交都移除掉,这太野蛮了。相比 reset,它不会改变现在的提交历史。因此,revert 可以用在公共分支上,reset 应该用在私有分支上。合并commit如果已经commit了怎么办,如果要撤回目前的commit,可以把它合并到上一个commit中git rebase -i HEAD~~在出现的两个提交信息的pick改为fixup3. 分支操作3.1 创建/查看/合并分支操作一览操作bash查看分支git branch查看本地和远程分支git branch -a在target分支上创建分支,没有则从当前分支git branch <branch-name> <target-branch>创建并切换分支git checkout -b <branch-name>合并某分支到当前分支git merge <branch-name>删除分支,只能删参与了合并的git branch -d <branch-name>强行删除git branch -D <branch-name>删除远程分支git push origin :<remote-branch-name>创建分支# 创建新分支git branch bug-fix# 查看分支,-a查看本地和远程的分支,-r查看远程分支,-l或没有只查看本地git branch -a# 切换到刚刚创建的分支git checkout bug-fix上面两个步骤可以合并为# 创建并切换到分支git checkout -b bug-fix如果修改一下本地文件之后在这个分支继续培育一个版本之后,怎么去合并到主分支呢git add *git commit -m “some change”# 切换到主分支git checkout master# 合并分支git merge bug-fix# 删除分支 (可选)git branch -d bug-fix如果master分支和新的分支都各自培育了版本,那么自动合并通常会失败,发生冲突conflict,此时需要打开文件解决冲突之后commit一个版本以完成合并git add *git commit -m “branch merge"这里提一下,merge的时候有几个主要模式,–no-ff、fast-forward,其中fast-forward是默认的fast-forward:在master开始的新分支前进了几个版本之后如果需要merge回来,此时master并没有前进,那么这个模式就是把HEAD与master指针指向新分支上,完成合并。这种情况如果删除分支,则会丢失分支信息,因为在这个过程中并没有创建commit。–no-ff:关闭默认的fast-forward模式,也就是在merge的时候生成一个新的commit,这样在分支历史上就可以看出分支信息。3.2 远程仓库操作操作一览操作bash克隆git clone <url>添加远程仓库git remote add <name> <url>删除远程仓库git remote rm <name>拉取git pull <remote-branch-name> <local-branch-name>推送本地所有分支到远程git push –all origin推送到远程同名分支git push origin <local-branch-name>推送本地分支到远程mastergit push origin <local-branch-name>:master把当前本地分支推送并创建到远程git push origin检出远程分支git checkout -b <new-local-branch-name> origin/<remote-branch-name>关于各个分支,哪些需要推送呢master分支是主分支,因此要时刻与远程同步;dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。直接clone在github上创建一个新的项目之后,比如叫learn-git,那么可以直接clone下来,注意创建的时候不要选择 Initialize this repository with a README,我们要的是一个空的仓库git clone https://github.com/SHERlocked93/learn-git.git这样在本地就直接创建了一个空的文件夹learn-git,当然里面有.git文件夹。也可以使用SSH地址来clone,速度会快一些,也不用每次推送都输入口令,推介使用这种git clone git@github.com:SHERlocked93/learn-git.git添加一个文件filename.txt之后git add filename.txtgit commit -m “add filename.txt"git push -u origin master这样就把本地新建的文件push到了远程仓库本地与远程建立关联如果已经有了本地工程文件夹,如何分享到github远程仓库呢,当然此时我们已经在github上创建了一个新的空白项目,还是叫learn-git,在本地文件夹中git init# 关联远程库git remote add origin git@github.com:SHERlocked93/learn-git.gitgit push -u origin master就可以了,如果你的远程仓库已经有了提交,那么在push之前需要# 允许不想干库合并git pull origin master –allow-unrelated-historiesgit push -u origin master先拉取远程分支,注意这里–allow-unrelated-histories允许两个不想干的分支强行合并,再push;这样在github的网站上还能看到commit记录。也可以强硬一点直接强行推送# -f 强行推送git push -u origin master -f这样本地仓库就直接把远程仓库覆盖了,且github上也看不到历史commit了,如果不想被同事枪击的话,还是推介上一种做法。同步远程仓库那么已经clone的仓库如果希望同步原仓库新的提交怎么办# 从远程分支拉取代码到本地git pull upstream master# push到自己的库里git push origin master3.3 多人协作多人协作的工作模式通常是这样:首先,可以试图用git push origin <branch-name>推送自己的修改;如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;如果合并有冲突,则解决冲突,并在本地提交;没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功从远程抓取分支,使用git pull,如果有冲突,要先处理冲突,add->commit->push。如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch –set-upstream-to <branch-name> origin/<branch-name>。4. 标签操作操作一览操作bash查看所有标签git tag新建标签git tag <tagname>新建并制定说明git tag <tagname> -m <message> <bash>查看标签说明git show <tagname>删除标签git tag -d <tagname>推送某个标签到远程git push origin <tagname>推送所有未推送到远程的本地标签git push origin –tags合并远程仓库的标签到本地git pull origin –tags删除远程标签git push origin :refs/tags/<tagname>如果要删除远程分支,需要# 首先删除本地tag,假如tag是v0.9git tag -d v0.9# 再从远程删除git push origin :refs/tags/v0.95. 提交格式type:feat: 新特性,添加功能fix: 修改bugrefactor: 代码重构docs: 文档修改style: 代码格式修改, 注意不是 css 修改test: 测试用例修改chore: 其他修改, 比如构建流程, 依赖管理.网上的帖子大多深浅不一,甚至有些前后矛盾,在下的文章都是学习过程中的总结,如果发现错误,欢迎留言指出~推介阅读:廖雪峰 - Git教程github实现本地仓库与远程仓库同步图解 Git 命令git基本操作,一篇文章就够了!团队协作中的 Github flow 工作流程git 命令大全附件Git常用命令速查表: ...

October 13, 2018 · 2 min · jiezi

30分钟学会Git - 在码云实践

不耍流氓,直接上操作!1. 本地仓库初始化$ cd ifast$ git init2. 新建远程仓库比如码云,获得项目地址https://gitee.com/icron/ifast.git3. 添加/关联远程仓库$ git remote add gitee https://gitee.com/icron/ifast.git先拉取一次代码$ git pull gitee master 这时会报错,意思是2个仓库没有关联,带上参数–allow-unrelated-histories再来一次$ git pull gitee master –allow-unrelated-histories这样就pull成功了,然后就可以正常操作了。4. 本地代码提交$ git add * $ git commit -m ‘初始化’ 5. 推送远程仓库$ git push gitee master或使用参数 -u 首次推送所有内容$ git push -u gitee master6. 新建开发分支本地新建开发分支dev(远程仓库可能不存在),并切换到新建的开发分支dev$ git checkout -b dev本地新建开发分支dev,从远程仓库gitee直接拉取开发分支dev,并切换到新建的开发分支dev$ git checkout -b dev gitee/dev7. 推送开发分支将更新推送dev分支到远程仓库,如果远程仓库不存在则默认会新建$ git push gitee dev8. 其他操作通过上面的实践操作,能进行git进行日常开发了,下面一些命令操作是日常操作的扩充。远程仓库git remote -v 查看远程仓库列表git remote remove gitee 移除远程仓库gitee分支操作git branch 查看所有分支,带*为当前分支git branch -d dev 删除dev分支git checkout dev 切换分支devgit branch dev 创建分支`devgit checkout -b dev 创建并切换分支devgit merge dev 合并dev分支到当前分支提交记录git log 查看提交记录git log –graph –pretty=oneline –abbrev-commit 格式化输出提交记录标签操作git tag v1.0 创建标签v1.0git push origin v1.0 推送单个标签git push origin –tags 一次性推送全部标签git tag -d v1.0 删除标签git push origin :refs/tags/v1.0 删除远程标签git tag 查看列表觉得有用记得收藏、点赞哦! ...

October 13, 2018 · 1 min · jiezi

Git 仓库大扫除

本文转载自我的博客Git 可以说是目前最受欢迎的版本管理工具了,很多团队也都在用它来管理自己的项目代码。在一个多人协作的项目中,往往采用的是一个分支一个特性进行开发,随着每天的代码提交、合并,仓库中会有越来越多的冗余分支。这么多死分支不仅会掩盖真正在使用的分支,而且也为管理带来不便。如果你像我一样,也经常被淹没在 git branch 或 git branch -r 返回的分支大海中,那么,就是时候考虑给你的 git 仓库做一次大扫除了!本地分支与远程分支大扫除之前,首先给自己做个深呼吸,回忆一下远程仓库和远程分支的概念。我们本地的仓库既保留有本地的分支,也保留有跟踪远程仓库的 remote 分支(类似 remotes/origin/** 这种的)。后者相当于是远程仓库分支在本地仓库的代理,每次 git fetch 或 git pull 时,都会将远程仓库的分支同步到本地对应的 remote 分支上。比如远程仓库新增了一个 feature/add_a 分支,那么我们在本地 git fetch 后,会得到一个 remotes/origin/feature/add_a 分支,这个名字表示 origin 这个远程仓库下的 feature/add_a,origin 是本地给远程仓库默认起的名字,你当然也可以改成别的名字。理清楚了本地分支和远程分支,本地仓库和远程仓库,接下来我们就动起手来做清理吧!本地分支清理查看我们本地的分支只需要执行一下git branch我们还可以找出所有已经合入到 master 的本地分支git checkout mastergit branch –merged针对这些已经合入的分支,如果确定已经不会使用的话,就可以将其删除了git branch -d feature/XXX如果十分确定所有合入的分支都不再需要了,那么可以考虑一次性解决((^*) 是匹配当前分支,其余 (master|dev) 部分可以根据自己项目的实际情况进行修改)git branch –merged | grep -v “(^*|master|dev)” | xargs git branch -d这么一来,就可以安全地删除所有已经不再需要的分支了。除此之外,也可以浏览一下没有合入 master 的本地分支,检查看看哪些分支已经废弃,不需要继续开发了git branch –no-merged针对这些分支,只用 git branch -d 命令会收到系统的善意提醒。如果十分确定可以删除,那么可以使用强制删除命令(一定要确认好啊)git branch -D feature/XXX经过这么一番清理,相信你的本地分支现在已经十分轻佻了,git branch 返回的结果看起来也十分清爽。接下来就来清理一下本地的远程分支。远程分支清理远程分支的查看只需要在 git branch 命令加一个 -r(–remotes) 参数即可git branch -r远程分支的清理,一方面是清理远程分支中,已经合入 master 的分支,另一方面是清理远程仓库已经删除了的分支,而本地还在跟踪的。第二种情况的清理非常简单,只需要执行git remote prune origin事实上,我们可以在每次 git fetch 时,添加一个参数 -p (–prune),这样每次 fetch 远程仓库时都可以顺手删掉本地多余的分支(建议将 git fetch -p 直接 alias 到 git fetch 命令~)。再来看第一种情况,虽然同样可以通过 git branch -r –merged 来查看已经合入 master 的分支,但由于远程分支不只是自己开发的,所以还需要别人的确认才能进行删除。好在我们可以在命令行的帮助下快速筛选出每个人的分支,然后就可以把这份统计摘要发给 TA 来确认。for branch in git branch -r --merged | grep -v HEAD; do echo -e git show --format="%ci %cr %an" $branch | head -n 1; done | sort -r | grep AUTHOR_NAME这行命令首先是过滤出所有已合入 master 的远程分支(git branch -r –merged | grep -v HEAD),然后遍历每个分支,展示(git show)其最后一次提交的绝对时间(%ci)、相对时间(%cr)和作者(%an)信息,按时间倒序排列(sort -r),最后过滤出作者是 AUTHOR_NAME 的分支。如果想查看更多的信息,可以在 git show 的 format 加上 %s(提交信息)和 %h(commit SHA1 前缀)这样一份报告,给到相关开发同学,确认之后,就可以执行批量清理了。注意,远程分支的删除应该到远程仓库去删除(否则下次 fetch 还会再拉下来),因此需要我们把这个删除动作 push 到远程仓库。最后,如果你 push 了删除动作到远程仓库,不要忘了提醒下其他同学 git fetch -p 来同步删除自己本地的远程分支哈!git push origin –delete feature/YYY找找我是谁如果自己经常换机器开发、push 代码,而且不同机器的 git config 不完全一样的话(比如我不同机器上 user.name 有的是英文名有的是中文名),提交的作者签名也不一样,这时还需要根据不同的 user.name 进行查找……不过好在我们有命令行,用以下命令就能得到仓库里所有提交过的作者了~git shortlog -s ...

October 10, 2018 · 1 min · jiezi

Git冲突解决(在同一个分支中)

1.在远程库中修改文件,在文件中加入“测试Git”,并提交合并到分支中2.在本地库中,先不进行pull,修改同一文件,在本地文件中加入“测试Git测试”,合并到本地库中3.在本地进行push操作,出现如下所示界面,提示push 被拒绝,表示和远程库有冲突4.在本地进行同步操作,synchronized workspace操作,界面会提示哪些文件有冲突可以看到冲突的是刚才我们在远程库和本地库对同一个文件写入不同语句产生的冲入,由我们自己解决冲突5.对文件进行修改后,保存修改的文件找到文件所在位置,右键,找到merge tool点击,然后点击 add to index ,进行commit到本地的操作可以看到项目上提示的只有向上的箭头,表示有没有没有push到远程库的文件,进行push操作在本地进行push操作后,查看远程库是否和本地文件一致,经查看,已经一致,说明操作成功。

September 29, 2018 · 1 min · jiezi

Git 系列文章

GIT 初识Git的基础操作Git的远程操作Git的分支管理Git标签操作Git团队协作Git 多账户管理Git的相关配置Git的子模块

September 26, 2018 · 1 min · jiezi

如何文明提交代码

程序员最烦的几件事:写测试,变量命名,还有填代码提交信息(commit message)。翻几个开源项目遍马上可以回味那作文凑字数的青春时光。其实 commit message 的作用远不止如此,经过简单的配置便可无痛成为代码提交的文明公民。Commit Message 的作用最起码的一点,项目的提交历史是其他人(包括未来的自己)了解项目的一个重要途径。好的提交历史可以方便其他人参与进来,也可以方便自己快速定位问题。此外,提交信息还可以用来触发 CI 构建,自动生成 CHANGELOG ,版本自动语义化提升…… 只需要一点点配置就可以干这么多,真是懒人必备。选择风格跟 Code Style 一样,Commit Message 也有各种风格。如果没什么特殊癖好推荐用基于 Angular ,后独立开来的 Conventional Commits 风格。它也基本是各个工具的默认配置,所以搭配起来不需要折腾。才不要又记什么规则虽然规则不多,但不一定能随时记住,特别是对新人,必须要有友好的方式提交。commitizen 是一个很好的选择,通过命令行回答几个问题即可填完信息,减轻了记忆负担。它是一个通用的工具,通过插件方式支持各种风格。我们选择 Conventional 需要安装cz-conventional-changelog 。npm install –save-dev commitizen cz-conventional-changelog然后配置 package.json 就可以通过 npm run commit 提交。{ “scripts”: { “commit”: “git-cz” }}另外 VSCode 用户也可以用 vscode-commitizen ,通过 ctrl+shift+p 或 command+shift+p 提交。Lint 一 Lint 万无一失没错,Commit Message 也有 Linter ,可对 Commit Message 进行检验,杜绝打字手残和浑水摸鱼。这里用 commitlint 配合 husky 实现自动检测。commitlint 也是通用的工具,需要同时安装风格配置。 husky 可以方便使用 git hooks ,在 commit 时触发 commitlint 。npm install –save-dev @commitlint/cli @commitlint/config-conventional husky项目根新建 commitlint.config.jsmodule.exports = { extends: [’@commitlint/config-conventional’]}配置 package.json{ “husky”: { “hooks”: { “commit-msg”: “commitlint -E HUSKY_GIT_PARAMS” } },}自动更新最后安装 standard-version 实现自动生成 CHANGELOG 和版本自动语义化提升。npm install –save-dev standard-version配置 package.json{ “scripts”: { “release”: “standard-version” }}第一次发布时可以用以下命令重置npm run release – –first-release以后直接 npm run release 即可。也可以手动指定版本:# npm run scriptnpm run release – –release-as minor# Ornpm run release – –release-as 1.1.0小红花贴起来在 README 中加入小徽章可方便其他人了解风格。完整配置安装npm install –save-dev commitizen cz-conventional-changelog @commitlint/cli @commitlint/config-conventional husky standard-version配置 package.json{ “scripts”: { “commit”: “git-cz”, “release”: “standard-version” }, “husky”: { “hooks”: { “commit-msg”: “commitlint -E HUSKY_GIT_PARAMS” } },}项目根新建 commitlint.config.jsmodule.exports = { extends: [’@commitlint/config-conventional’]}【完】 ...

September 25, 2018 · 1 min · jiezi

git命令笔记

0、git管理的是修改而不是文件!1、在 git Bash 上设置用户名和emailgit config –global user.name “Cai"git config –global user.email “1805800867@qq.com"查看:git config –list2、在空白目录 “test” 下创建git仓库,(test文件夹就是工作区)git init3、将仓库目录下的文件 test.txt 添加到暂存区git add test.txt4、将暂存区下的文件提交到当前分支git commit -m “提交的描述"5、查看仓库中文件的状态: 是否有文件改动了、是否有 add 过的文件git status6、查看文件具体修改的内容git diff test.txt7、当前版本出错,想要版本回退时从版本日志中寻找合适的版本,打印版本日志:git log8、回退到之前的版本git reset –hard HEAD^ //回退到前一个版本git reset –head 1094a //根据commit id回退到指定版本(commit id写前几位就好)git reset –hard HEAD10 //HEAD后面的数字10表示回退到上十个版本9、回退到之前版本后后悔了,再变回来必须知道该版本的commit idgit reflog //查看命令记录git reset –hard 1094a //回退到指定版本cat test.txt //查看该文件内容10、撤销工作区的修改(没有添加到暂存区)git checkout – test.txt //撤销对test.txt的修改11、撤销暂存区的修改git reset HEAD test.txt //撤销对暂存区中test.txt的修改12、从版本库中删除文件git rm test.txtgit commit -m “删除了test.txt文件"如果误删:git checkout – test.txt //还原13、如何将本地git仓库上传至GitHub1、打开GitBash输入: ssh-keygen -t rsa -C “110120119@qq.com” //生成公钥和私钥2、登录你的GitHub,并在设置中添加 SSH keys ,放入公钥。3、在GitHub中新建一个空仓库,仓库建好后可以选择其列出的第二项推送本地仓库的方式。4、详细参考链接: https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013752340242354807e192f02a44359908df8a5643103a00014、多人协作时从GitHub远程库克隆仓库git clone git@github.com:GithubName/test.git15、多人协作时,采用分支管理: 创建不同的分支,每个人在不同的分支上工作,最后合并分支。git branch //查看分支git branch name //创建分支git checkout name //切换分支git checkout -b name //创建并切换分支git branch -d name //删除分支(只能删已完成合并的分支)git branch -D name //强行删除分支(删未合并的分支)git merge name //合并 name 分支到当前分支git merge –no-ff -m “这里合并了dev分支” dev //使用普通模式合并分支,使其有据可查git log //查看分支历史//同一段内容在不同分支上不一致时无法合并分支,先解决冲突后再合并,然后删除创建的分支//master分支是主分支,通常不直接在主分支上修改,而仅用来发布新版本//可创建一个dev分支,所有人都在dev分支上创建自己的分支,所有修改都提交到dev分支,最终将dev分支作为新版本提交到master分支16、暂存未完成修改的分支git stash //工作只进行到一半没法提交时,先把工作现场存起来,下次再做git stash list //查看保存的工作区列表git stash pop //恢复工作区并删除暂存的stashgit stash apply //恢复工作区,不删stashgit stash drop //删除stash//比如是在dev分支上创建的工作分支,则到dev分支上恢复工作区17、多人协作时,使用远程分支git remote //查看远程库,可以看到远程库名字,默认名:origingit remote -v //查看远程库详细信息,显示可以抓取和推送的origin的地址git push origin master //推送本地主分支(master)到远程分支(origin)git push origin dev //推送本地开发分支(dev)到远程分支//通常需要推送主分支和开发分支到远程分支中,而每个人基于开发分支自己创建的工作分支,视情况推送。抓取远程分支时,只能clone主分支master,如果要在dev分支工作就需要创建远程dev分支到本地git checkout -b dev origin/dev //在本地创建远程的dev分支,然后就可以在dev分支创建自己的工作分支了git push origin dev //时不时推送dev分支到远程18、如果向远程分支推送失败//如果推送失败,因为你试图推送的提交与你的小伙伴的提交冲突了。git pull //把最新的提交抓下来,然后在本地合并,解决冲突后再推送git branch –set-upstream-to=origin/dev dev //如果git pull 失败,可能忘了设置dev分支与远程dev分支的链接// 再git pull ,然后推送,合并分支19、标签管理//为了方便管理,可以为每次提交打一个标签,比如版本号git tag v1.0 //为当前分支创建标签git tag //查看所有标签git tag v0.9 0536a //如果忘了打标签,可以指定使用git log查到该分支版本的 commit id 打标签git show v1.0 //显示标签信息git tag -a v1.0 -m “标签描述” 03366b //创建带说明的标签//标签都是创建在本地的,不会自动推送到远程git tag -d v1.0 //删除本地标签git push origin v1.0 //推送一个标签到远程git push origin –tags //推送所有本地标签到远程git push origin :refs/tags/v1.0 //删除远程标签 20、使用码云//码云是国内的Git托管服务平台,和Git不同的是码云可以提供免费的私有仓库,而Git的私有仓库是收费的。//和GitHub一样,注册码云并添加公钥后在码云创建一个项目,然后使用下面的命令关联码云的远程库git remote add gitee git@gitee.com:cai/testgit.git //注意码云的远程库是 gitee 而不是origin(可以使用 git push gitee master 推送了)git remote -v //查看远程库信息git remote rm origin //删除origin远程库(origin是GitHub的远程库)git remote add github git@github.com:OnlyChangeMyself/test.git //重新关联GitHub的远程库,此时GitHub的远程库叫github了而不是origin(可以使用git push github master)21、配置别名git config –global alias.sta status //使用git sta就等于git status了git config –global alias.cmt commit //git cmt等于git commitgit config –global alias.lg “log –color –graph –pretty=format:’%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset’ –abbrev-commit” //git lg22、搭建Git服务器//其实就是搭建私有仓库//推荐使用Linux服务器如Ubuntu或Debian//假设你有sudo权限的账号第一步:sudo apt-get install git //安装Git第二步:sudo adduser git //创建一个Git用户,用来运行Git服务第三步:创建证书登录:///收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个第四步,初始化Git仓库://先选定一个目录作为Git仓库,在该目录下输入命令(比如目录:/srv):sudo git init –bare sample.gitsudo chown -R git:git sample.git第五步:禁用shell登录,通过编辑/etc/passwd文件完成git❌1001:1001:,,,:/home/git:/bin/bash改为:git❌1001:1001:,,,:/home/git:/usr/bin/git-shell第六步,克隆远程仓库:git clone git@server:/srv/sample.git23、参考自[参考自廖雪峰的官方网站][1] ...

September 24, 2018 · 2 min · jiezi