iOS開發經驗總結(持續更新中)

本文會持續記錄自己在學習、工作中,接觸的和iOS開發相關的各種技術。包括寫代碼時容易忽視的細節問題,項目中接觸到實用技術以及優秀的三方框架。歡迎收藏,點贊,若有不足歡迎各位指出來一起探討,共同進步。

Section One — Coding Tips

1.為私有方法名加前綴

  • 這條建議是我最近看《Effective Objective-C 2.0》才知道的。
  • 因為一個類要做的事情通常比外面看到的要多。在·m文件中,經常要寫一些內部使用的代碼。而我們應該給這些方法加上某些前綴,這有助于調試,因為據此很容易就能把公共方法和私有方法區分開。
  • 具體使用何種前綴完全可以根據個人喜好來,沒有固定標準。
    • 但有一點要注意:蘋果官方保留用單一下劃線作為前綴命名私有方法
  • 如果你想模仿蘋果的寫法也使用單一下劃線,很可能在無意中重寫了父類的同名方法,造成很多莫名其妙的問題。
  • 我個人對于私有方法喜歡以 p_methordName 的形式命名,p即代表pravite.

2.建議書寫枚舉模仿蘋果——在列出枚舉內容的同時綁定了枚舉數據類型NSUInteger,這樣帶來的好處是增強的類型檢查和更好的代碼可讀性,示例:

typedef NS_ENUM(NSUInteger, GPSectionType) {
    GPSectionTypeNone              = 0,
    GPSectionTypeNews              = 1 ,
    GPSectionTypeInformation      = 2,
};

3.頭文件 #import的順序

  • 寫法模板
#import <系統庫>
#import <第三方庫>
#import “其他類”
  • 盡量按照先系統類 第三方類 自己寫的類順序導入 中間不能有空格
  • 建議的寫法
#import<UIKit/UIkit.h>
#import<Google/Analytics.h>
#import"GPCustomView.h

4.@Class的寫法

  • 寫法模板:@class class1, class2;
// 建議的寫法
@class UIView, UIImage;
// 不建議的寫法
@class UIView;
@class UIImage;

5.聲明const的字符串

  • 開頭用k標識
  • 推薦k+模板名字首字母大寫+作用名稱 防止和其他的重復
  • 比如:CartViewModel類需要聲明更新購物車列表的通知
    • kCVMNoticationUpdateCartList

6.方法盡量控制最多五十行

  • 一個方法內部最多五十行
  • 如果超過就精簡代碼 就分開方法寫
  • 方便之后進行熱修復 代碼重構

7.注釋一定要寫

  • 自己管理的類一定注釋屬性用途 方法的用途 參數的說明

  • 屬性如果設置默認值 一定注明默認值是什么

  • 如果方法內部存在邏輯判斷 方法跳轉 一定注釋判斷用法 方法跳轉用法

  • 除了初始化操作

  • 其他聲明變量 賦值 判斷 應該注明注釋用途

  • 方法注釋

/**
 *  @brief 直播間發送禮物
 *
 *  @param gift     禮物
 *  @param groupId  直播間id
 *  @param count    數量
 *  @param success  成功回調
 *  @param failure  失敗回調
 */
 
 + (void)readySendGiftWithGift:(MoerLiveRoomGift*)gift
                      groupId:(NSString*)groupId
                        count:(NSInteger)count
                      success:(void(^)(Goods *goods))success
                      failure:(Failure)failure;                
/**
 *  @brief 根據字典信息實例化訂單
 *
 *  @param dictionary 字典信息
 *
 *  @return 訂單實例
 */
-(instancetype)initWithDictionary:(NSDictionary*)dictionary;

  • 屬性注釋
/**
 *  打賞對象
 */
@property (nonatomic, copy) NSString *targetId;

  • 枚舉注釋
typedef NS_ENUM(NSInteger, MoerGoodsType) {
    /**
     *  無
     */
    MoerGoodsTypeNone,
    /**
     *  文章
     */
    MoerGoodsTypeArticle = 1,
    /**
     *  活動
     */
    MoerGoodsTypeActivity = 2
}

8.頭文件引入其他類的時候使用@class

  • 可以防止互相引入導致編譯失敗,造成不容易查找的bug
  • 同時在.m文件中使用#import導入對應的類

9.多使用pragma mark

  • 尤其是一個控制器包含非常多的業務邏輯,可以讓結構更加清晰

10.控件的命名規范

  • 不要使用簡寫,password不要寫成pwd,button不要寫成btn等;
  • UILabel結尾加上Label;
  • UIImageView結尾記上ImageView
  • 等等讓其他的編程人員看名字就知道變量的用法 和屬于什么控件

11.對于#define宏命名

  • 單詞全部的大寫 單詞之間用_分割
  • 建議的寫法
#define NS_AVAILABLE_IOS(_ios) CF_AVAILABLE_IOS(_ios)

12.對于局部的變量盡量的初始化

  • 局部的變量要初始化 屬性有默認的值 所以我們不必須對于屬性進行初始化
  • 我之前遇到的一個BUG就是int類型沒有初始化給我默認Nan造成崩潰
//正確的寫法
int index = 0;
//錯誤的寫法
int index;
  • 對于一些對象判斷是否賦值可以不進行初始化 但是對于一定不會為nil要進行初始化

13.block的命名規范

  • 之前研究過很多的第三方的命名 對于蘋果官方的沒找到
  • 有CallBack結尾 Complete結尾 Block結尾 還有CompletionHandle結尾的
  • 我看到蘋果很多的結尾都是用CompletionHandle結尾
// 建議的寫法
typedef void(DidUpdateViewCompletionHandle)(void)
// 不建議的寫法
typedef void(DidUpdateViewCallBack)

14.在dealloc方法中移除通知

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

15.屬性要盡量使用懶加載

  • 我們一個界面有很多控件
  • 利用懶加載可以美化代碼
  • 所有的懶加載放在Getter的mark的下面

16.多使用字面量

  • NSString @“”
  • NSNumber @()
  • NSDictionary @{}
  • NSArray @[]

17.為第三方類添加分類添加前綴

  • 比如為系統UIView添加分類Add的添加前綴
@interface UIView (GP_Add)
- (void)gp_addCustomView:(CustomView *)customView;
@end;

18.數組和字典最好指定元素的類型

NSArray<NSString *> *names = [NSArray array];

Section Two — Work Experience

1.建議加載xib,xib名稱用NSStringFromClass(),避免書寫錯誤

// 推薦寫法
[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([GPTableViewCell class]) bundle:nil] forCellReuseIdentifier:ID];

// 不推薦寫法
[self.tableView registerNib:[UINib nibWithNibName:@"GPTableViewCell" bundle:nil] forCellReuseIdentifier:ID];

2.自定義cell的時候,將重用標識符同cell文件綁定在一起,而不是在控制器里定義一堆重用標識符

  • 在.h中
#import "GPBaseCell.h"

UIKIT_EXTERN NSString * const GPContentCelltCellIdentifier;

@interface GPContentCell : GPBaseCell

@end

  • 在.m中
#import "GPContentCell.h"

NSString * const "GPContentCell = @"GPContentCell";

@interface GPContentCell ()
@property (weak, nonatomic) IBOutlet UILabel *contentLabel;
@end

@implementation MoerQAAskerContentCell

- (void)awakeFromNib {
    [super awakeFromNib];
    self.selectionStyle = UITableViewCellSelectionStyleNone;
    self.contentLabel.textColor = [UIColor redColor];
}
  • UIKIT_EXTERN簡單來說,就是將函數修飾為兼容以往C編譯方式的、具有extern屬性(文件外可見性)、public修飾的方法或變量庫外仍可見的屬性
  • 參考資料

3.使用XIB創建自定義View

  • 我們創建一個繼承自UIView的類時,底下Also Creat XIB file處于灰色不可選擇的狀態。或許是蘋果官方不建議這樣做,但我們仍然可以單獨創建一個View文件將其關聯起來。
  • 在.h文件中聲明一個初始化方法
- (instancetype)initWithXib;
  • 在.m中實現它
- (instancetype)initWithXib {
    self = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil] lastObject];
    // 初始化設置調整UI樣式
    ...
    return self;
}

4.善于利用autoresizingMask技術

  • 用于處理比較簡單的、單一的父子視圖關系
  • 一般情況下,確定一個子控件在其父控件中的位置,我們只需要確定4個方向中的兩個有效方向就夠了,如果多于兩個有效方向,那么多出來的方向約束會被替代。具體說來就是,4個方向的約束線是有優先級的,頂部的約束線優先級高于底部的約束線,左邊的約束線優先級高于右邊的約束線。如果你同時約束了左邊和右邊,那么起作用的就是左邊;如果你同時約束了上邊和下邊,那么起作用的就是上邊;如果你同時約束了4個方向,那么起作用的是左上角。為了保證約束有效,不能同時約束上、下或者是左、右。
  • 參考資料

5.拉伸圖片

  • 有些時候UI給的圖片不能滿足我們的需求,這個時候我們就要自己簡單處理一下圖片。
  • 比如以某edgeInsets進行拉伸圖片
  • 涉及到的方法
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(5_0); // create a resizable version of this image. the interior is tiled when drawn.
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode NS_AVAILABLE_IOS(6_0); // the interior is resized according to the resizingMode

6.使用SDWebImage給button設置圖片

// 第一步:導入頭文件
#import <SDWebImage/UIButton+WebCache.h>
// 第二步:調用方法并設置占位圖片
[self.avatarButton sd_setImageWithURL:[NSURL URLWithString:model.avatarUrlString] forState:UIControlStateNormal placeholderImage:[UIImage imageNamed:@"PlaceholderImage"]];

7.使用SDWebImage加載gif圖片

// 第一步:導入頭文件
#import "UIImage+GIF.h"
// 第二步:調用方法
    UIImage *hoopImage = [UIImage sd_animatedGIFNamed:@"hula_hoop"];
    self.hoopImageView = [[UIImageView alloc] initWithImage:hoopImage];
    self.hoopImageView.frame = CGRectMake(10, 10, 100, 100);
    [self.view addSubview:self.hoopImageView];

8.使用dSYM文件查找線上程序的crash日志

  • 什么是 dSYM 文件
    • Xcode編譯項目后,我們會看到一個同名的 dSYM 文件,dSYM 是保存16進制函數地址映射信息的中轉文件,我們調試的 symbols 都會包含在這個文件中,并且每次編譯項目的時候都會生成一個新的 dSYM 文件
    • 位于 /Users/<用戶名>/Library/Developer/Xcode/Archives 目錄下,對于每一個發布版本我們都很有必要保存對應的 Archives 文件 。

  • dSYM 文件有什么作用
    • 當我們軟件 release 模式打包或上線后,不會像我們在 Xcode 中那樣直觀的看到用崩潰的錯誤,這個時候我們就需要分析 crash report 文件了,iOS 設備中會有日志文件保存我們每個應用出錯的函數內存地址
    • 通過 Xcode 的 Organizer 可以將 iOS 設備中的 DeviceLog 導出成 crash 文件,這個時候我們就可以通過出錯的函數地址去查詢 dSYM 文件中程序對應的函數名和文件名。
    • 大前提是我們需要有軟件版本對應的 dSYM 文件,這也是為什么我們很有必要保存每個發布版本的 Archives 文件了。

  • 如何將文件一一對應
    • 每一個 xx.app 和 xx.app.dSYM 文件都有對應的 UUID,crash 文件也有自己的 UUID,只要這三個文件的 UUID 一致,我們就可以通過他們解析出正確的錯誤函數信息了。

  • 1.查看 xx.app 文件的 UUID,terminal 中輸入命令 :
    dwarfdump --uuid xx.app/xx (xx代表你的項目名)

  • 2.查看 xx.app.dSYM 文件的 UUID ,在 terminal 中輸入命令:
    dwarfdump --uuid xx.app.dSYM

  • 3.crash 文件內第一行 Incident Identifier 就是該 crash 文件的 UUID。


9.block的注意事項

  • 在類中聲明block為屬性時,如果使用assgin修飾,那么它被放到了棧中,方法一過就會被銷毀,
  • 所以,盡量使用copy作為修飾詞,這樣一來block就被存放到了堆中,生命周期就會延長,保證block不會被立即銷毀;
  • 要防止循環引用,所以在block外部通常要先弱引用一次,然后在block內部強引用一次。
  • __weak typeof(self) weakSelf = self;
  • __strong typeof(self) strongSelf = weakSelf;
  • block使用的時候要先進行判斷
if (self.backBlock) {
    self.backBlock(self.textView.text)
}


10.不要把本地調試的代碼提交到git上

  • 如果在提交前忘記改回來,要善于利用宏
  • 下面的代碼只會在debug模式下運行
  • 如果切換到release模式不會運行
#ifdef DEBUG
    isDebug = YES;
#else
    isDebug = NO;
#endif

11.使用自定義標簽警告

  • // TODO:標識將來要完成的內容;
  • // FIXME:標識以后要修正或完善的內容。
  • // ???: 疑問的地方
  • /// !!!: 需要注意的地方

12.使用runtime關聯對象


13.使用contentMode讓圖片長得好看


14.控件字體顏色設置相同時使用IBOutletCollection

  • 對于很多控件我們有的時候可能要設置相同的顏色或者字體大小,這個時候我們不必把每一個控件都拖成屬性,而是使用IBOutletCollection統一設置
  • 參考資料1
  • 參考資料2

15.修改狀態欄字體顏色

// 首先寫一個屬性
@property (nonatomic, assign) UIStatusBarStyle statusBarStyle;
// 根據具體需求來修改狀態欄的樣式
self.statusBarStyle = UIStatusBarStyleLightContent;// 白色
self.statusBarStyle = UIStatusBarStyleDefault; // 黑色
// 告訴系統更新狀態欄樣式
[self setNeedsStatusBarAppearanceUpdate];
// 重寫該方法,將新的樣式返回給系統
- (UIStatusBarStyle)preferredStatusBarStyle {
    return self.statusBarStyle;
}

16.關閉刷新section的動畫效果

// 雖然動畫效果選擇的是UITableViewRowAnimationNone
// 但實際上還是會動畫效果
 [self.tableView reloadSections:[[NSIndexSet alloc] initWithIndex:GPSectionTypeNews] withRowAnimation:UITableViewRowAnimationNone];
  • 正確做法
[UIView performWithoutAnimation:^{
            [self.tableView reloadSections:[[NSIndexSet alloc] initWithIndex:GPSectionTypeNews] withRowAnimation:UITableViewRowAnimationNone];
        }];

17.善于利用round/ceil/floorf函數

  • round:如果參數是小數,則求本身的四舍五入。
  • ceil:如果參數是小數,則求最小的整數但不小于本身.
  • floor:如果參數是小數,則求最大的整數但不大于本身.
Example:如何值是3.4的話,則
3.4 -- round 3.000000
    -- ceil 4.000000
    -- floor 3.00000

18.APP內撥打電話

  • 方法一
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://010-88888888"]];

  • 方法二
#import <UIKit/UIWebView.h>

UIWebView * callWebview = [[UIWebView alloc]init];
[callWebview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"tel:010-88888888"]]];
[[UIApplication sharedApplication].keyWindow addSubview:callWebview];
  • 區別
區別一:第一種會先跳出程序到系統的打電話程序,第二種是一直都在自己的app中運行,沒有出去過。
區別二:第一種觸發直接到打電話界面,第二種會先彈出一個對話框,可以選擇打不打電話,對話框如下。

19.善于利用UIStackView


20.iOS中常用動畫詳解


21.使用NSTextAttachment實現圖文混排

//     
    NSMutableAttributedString *titleString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ ", article.title]];
    NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithData:nil ofType:nil];
    textAttachment.image = [UIImage imageNamed:@"icon"];
    CGFloat offsetY = -1.0;
    textAttachment.bounds = CGRectMake(0, offsetY, textAttachment.image.size.width, textAttachment.image.size.height);
    NSAttributedString *textAttachmentString = [NSAttributedString attributedStringWithAttachment:textAttachment];
    [titleString insertAttributedString:textAttachmentString];

22.TextKit的學習


23.支付相關


24.關于dispatch_semaphore的使用


25.NSStringFromSelector(_cmd)說明

  • _cmd 代表本方法的名稱

  • _cmd是隱藏的參數,代表當前方法的selector,他和self一樣都是每個方法調用時都會傳入的參數,動態運行時會提及如何傳的這兩個參數,
    你在方法里加入CCLOG(@"%@, %@",NSStringFromSelector(_cmd),self);語句之后,執行這個方法就會輸出方法的名稱,
    這樣做是為了跟蹤查看方法調用的前后順序,或者想看看程序到底在那個方法內部崩潰的!

  • 在Apple的官方介紹里看到輕描淡寫的說了一句:“The _cmd variable is a hidden argument passed to every method that is the current selector”,其實說的就是_cmd在Objective-C的方法中表示當前方法的selector,正如同self表示當前方法調用的對……

26.iOS方法警告

  • 當蘋果SDK升級時廢棄某些方法,就需要方法警告。

  • 外部調用方法警告

__deprecated_msg("方法廢棄,請使用...替換")
  • 當前方法警告
__attribute__((visibility("警告")));
- (void)test __deprecated_msg("方法廢棄,請使用...替換") __attribute__((visibility("方法廢棄")));


27.友盟推送踩的坑

  • 首先友盟的推送是分為開發環境和生產環境,開發環境就是指我們在開發階段,應用還沒有上架到app store的時候,這時候我們按照友盟的官方文檔集成友盟消息推送就可以了。
  • 然后要測試的時候,這時候選擇測試模式進行測試,要在下面的方法中獲取當前設備的device token,然后測試模式添加測試設備,只要上傳的證書沒有錯誤,發送消息手機就可以收到推送消息了
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSLog(@"%@",[[[[deviceToken description] stringByReplacingOccurrencesOfString: @"<" withString: @""]
                  stringByReplacingOccurrencesOfString: @">" withString: @""]
                 stringByReplacingOccurrencesOfString: @" " withString: @""]);
}

  • 開發環境只能在測試模式下測試,消息列表那邊只能是app上線后,變成生產環境了才可以在消息列表發送消息測試。
  • app上線后,第一天一般發送推送消息是失敗的,因為device token在友盟那邊的入庫是有一天的延時的,具體可以看友盟上的這篇文章
  • 關于app點擊消息跳轉到指定頁面,分為當前app是在前臺還是后臺后者未運行,所以需要在
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  • 兩個方法里面寫頁面的跳轉,這個需要和后臺約定好傳過來的消息需要跳轉到什么頁面,再自己做跳轉,頁面跳轉只能自己在代碼中進行操作.

  • 推送消息一直顯示發送失敗,不知道該如何查找原因,找了客服很多次,說device token無效,重新獲取,可是重新獲取很多次也還是無效
  • 后來碰到好心人建議查看證書的包名和bundle ID是否一致,于是把導出的上傳到友盟的推送證書在鑰匙串中打開,發現包名確實不一樣了,但是證書制作過程沒有出錯的,所以想不通,把證書刪除了,重新導出,上傳,OK。可以推送了。如果用戶第一次打開app 沒有允許推送,后面在設置中打開允許推送也是可以的,因為在第一次打開和每天的第一次運行app的時候都會發送token給友盟的服務器,所以推送開關的開啟和關閉不影響token。
  • 最后如果需要在生產環境下將應用程序安裝到設備上測試,或者APP并沒有上線也需要推送組件,要以Ad Hoc方式打包應用

28.配置Gitlab

  • GitLab是企業版的GitHub,并且GitLab是開源的,也就是說可以部署到自己的內網上。
  • 如果配置好了SSH公鑰還是不能通過Sourcetree把公司的代碼拉到本地的電腦上,可能是你的老大忘了把你的Gitlab賬號開通權限
  • GitLab的簡單使用

29.過濾掉字符串前后的空格

  • 有時候服務端返回的數據前后會帶\n
  • 我們可以調用下面的方法將它去掉
 NSString* trimedURL = [stringURL stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

Section Three — Third Party

1.一款非常強大的文字編輯器


2.實現頂部彈窗的HUD


3.非常好用的一款加載彈窗


4.每一個網絡請求封裝成對象的網絡庫


5.讓響應手勢變得更簡單


6.讓每一個試圖控制器擁有獨立的導航欄


7.繪制圖表、折線圖的框架


8.一個比UISegmentedControl更好用的東西


9.輪播圖必備


10.tableView算高神器


11.超級強大的開源框架


12.小抽屜展示


13.側滑抽屜


14.夜間模式


15.圖片瀏覽器


16.HTML標簽解析


Section Four — Development Tool

1.捕捉網絡請求 — Charles


2.切換host的工具 — Gas Mask


3.高效的編輯器 — Subline Text


4.模擬發送網絡請求 — Postman


5.圖形化Git工具 — SourceTree


6.分析他人APP界面 — Reveal


7.翻墻必備 — Shadowsocks


8.快捷鍵太多記不住? — Cheetsheet


Section Five — About Git

很多人做iOS開發,可能先接觸方便好用的Sourcetree,記住了合并代碼的那幾個步驟,然后才接觸git。為了能更好的理解Sourcetree做的每一步,很有必要學習博大精深的git,以下內容為本人惡補git知識時的筆記,感謝廖雪峰老師寫的git教程。


  • 創建一個文件夾(默認路徑:/Users/fsl/learngit)
    • mkdir learngit
  • 進入該文件夾
    • cd learngit
  • 顯示當前目錄
    • pwd
  • 初始化git倉庫
    • git init
  • 把文件添加到git倉庫
    • git add <file>
    • git commit
      • git commit -m "提交信息"


  • 查看當前倉庫的狀態
    • git status
  • 查看當前倉庫某個文件的改變
    • git diff readme.txt
  • 顯示從最近到最遠的提交日志
    • git log


  • 版本回退
    • git reset --hard HEAD^
    • HEAD指向的版本就是當前版本,因此,Git允許我們在版本的歷史之間穿梭,使用命令git reset --hard commit_id。
    • 穿梭前,用git log可以查看提交歷史,以便確定要回退到哪個版本。
    • 要重返未來,用git reflog查看命令歷史,以便確定要回到未來的哪個版本。



版本庫(Repository)

  • 查看工作區和版本庫里最新文件的區別

    • git diff HEAD -- readme.txt
  • 撤銷修改

    • git checkout -- readme.txt
    • git checkout -- file命令中的--很重要,沒有--,就變成了“切換到另一個分支”的命令


  • 撤銷已經提交到暫存區的修改(重新放回工作區)

    • git reset HEAD readme.txt
    • git reset命令既可以回退版本,也可以把暫存區的修改回退到工作區。當我們用HEAD時,表示最新的版本。
  • 刪除文件

    • rm test.txt
    • git checkout其實是用版本庫里的版本替換工作區的版本,無論工作區是修改還是刪除,都可以“一鍵還原”。
    • 命令git rm用于刪除一個文件。如果一個文件已經被提交到版本庫,那么你永遠不用擔心誤刪,但是要小心,你只能恢復文件到最新版本,你會丟失最近一次提交后你修改的內容。

添加到遠程倉庫

  • 關聯一個遠程庫
  • git push -u origin master (第一次推送master分支的所有內容)
    • 把本地庫的內容推送到遠程,用git push命令,實際上是把當前分支master推送到遠程。
    • 由于遠程庫是空的,我們第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在以后的推送或者拉取時就可以簡化命令。
  • 此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;
  • 從現在起,只要本地做了提交,就可以通過
    • git push origin master
    • 把本地master分支的最新修改推送至GitHub,現在,就擁有了真正的分布式版本庫!

查看分支

  • git branch

切換分支(創建新分支)

  • git checkout -b dev
  • git checkout命令加上-b參數表示創建并切換,相當于以下兩條命令:
    • $ git branch dev
    • $ git checkout dev
      • Switched to branch 'dev'
  • 切換分支
    • git checkout <name>

合并指定分支(dev)到當前分支(master)

  • git merge dev

刪除分支

  • git branch -d dev
  • 查看分支
    • git branch

查看分支圖

  • git log --graph
  • git log --graph --pretty=oneline --abbrev-commit

分支管理策略

  • 通常情況下,合并分支時,Git會使用Fast Forward(快進)模式,即改變指針指向


  • 使用Fast Forward模式有一個缺點,就是刪除分支后,會丟掉分支信息。
  • 如果要強制禁用Fast Forward模式,Git就會在merge時生成一個新的commit,這樣的話在分支歷史上就能看到分支信息。
    • git merge --no-ff -m "merge with no-ff" dev
    • 因為本次合并會創建一個新的commit,所以要加上-m 參數,把commit的描述寫進去。

Bug分支

  • 修復bug時,我們會通過創建新的bug分支進行修復,然后合并,最后刪除;
  • 當手頭工作沒有完成時,先把工作現場git stash一下,然后去修復bug,修復后,再git stash pop,回到工作現場。
  • 查看暫存列表
    • git stash list
  • 恢復工作現場
    • 方式一:用git stash apply恢復,但是恢復后,藏匿內容并不刪除,需要你用git stash drop來刪除;
    • 方式二:用git stash pop,恢復的同時把stash內容也刪了

Feature分支

  • 添加一個新功能時,你肯定不希望因為一些實驗性質的代碼,把主分支搞亂了,所以,每添加一個新功能,最好新建一個feature分支,在上面開發,完成后,合并,最后,刪除該feature分支。
  • 有一種可能是該分支開發到一半,被告知新功能取消。此時執行 git branch -d 分支名,是直接刪不掉分支的
    • git會提醒你,該分支還沒有被合并,如果刪除將丟失掉修改
    • 如果要強行刪除,需要使用命令git branch -D 分支名。

多人協作

  • 多人協作的工作模式通常是這樣:
    • 首先,可以試圖用git push origin branch-name推送自己的修改;
    • 如果推送失敗,則因為遠程分支比你的本地更新,需要先用git pull試圖合并;
    • 如果合并有沖突,則解決沖突,并在本地提交;
    • 沒有沖突或者解決掉沖突后,再用git push origin branch-name推送就能成功!
  • 如果git pull提示“no tracking information”,則說明本地分支和遠程分支的鏈接關系沒有創建,用命令git branch --set-upstream branch-name origin/branch-name。
  • 查看遠程倉庫信息
    • git remote -v
  • 如果新建的分支不推送到遠程,對其他人就是不可見的
  • 從本地推送分支,使用git push origin branch-name,如果推送失敗,先用git pull抓取遠程的新提交;
  • 在本地創建和遠程分支對應的分支,使用git checkout -b branch-name origin/branch-name,本地和遠程分支的名稱最好一致

標簽管理

  • 發布一個版本時,我們通常先在版本庫中打一個標簽(tag),這樣,就唯一確定了打標簽時刻的版本。將來無論什么時候,取某個標簽的版本,就是把那個打標簽的時刻的歷史版本取出來。所以,標簽也是版本庫的一個快照。
  • tag就是一個讓人容易記住的有意義的名字,它跟某個commit綁在一起。
  • 創建標簽
    • git tag <name>用于新建一個標簽,默認為HEAD,也可以指定一個commit id
    • git tag -a <tagname> -m "blablabla..."可以指定標簽信息;
    • git tag -s <tagname> -m "blablabla..."可以用PGP簽名標簽;
    • 命令git tag可以查看所有標簽
  • 操作標簽
    • 刪除標簽
      • git tag -d <tagname>
    • 推送一個本地標簽到遠程
      • git push origin <tagname>
    • 一次性推送全部尚未推送到遠程的本地標簽
      • git push origin --tags
    • 刪除遠端的標簽
      • 先刪除本地的標簽 git tag -d <tagname>
      • 在使用git push origin :refs/tags/<tagname> 刪除遠端的標簽

忽略文件

  • 忽略某些文件時,需要編寫.gitignore
  • .gitignore文件本身要放到版本庫里,并且可以對.gitignore做版本管理

使用rebase而不是merge

  • 為了讓提交代碼的時間線是筆直的一條線,而不是各種分叉,我們要使用rebase(變基)
  • 關于rebase的知識可以看下面的鏈接
  • git rebase使用筆記

最后

學而時習之,不亦說乎。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容