作者| idaxia
6.1 名詞定義
在學習 Git 的diff命令之前,我們先來統一 一下兩個名詞的理解,分別是工作區和暫存區。
6.1.1 工作區
工作區,指的是當前正在編輯的文件,將還沒有修改的內容通過git add命令暫存起來;比如我現在修改了index.php文件中的一行代碼,沒有執行git add index.php命令,那么 index.php 便處于工作區狀態。
6.1.2 暫存區
暫存區,指的是文件修改之后并且通過git add命令臨時存儲到版本記錄里了,但還沒有正式通過git commit提交的階段;比如我現在新增一個test.php文件,使用了git add test.php命令,那么此時, test.php 文件的改動就已經進入到了暫存區。
6.2 比較工作區變動
現在我編輯了index.php文件,并且在里面加入了內容,如果我想通過 git 命令查看增加了哪些內容,參考命令如下
git diff
執行命令之后,綠色部分代表增加的內容,紅色部分代表刪除的內容,執行結果如下圖所示:
在圖中可以看到我在 index.php 中增加了。
6.3 比較暫存區變動
有些時候,我們可能已經通過git add命令,將某些文件從工作區添加到暫存區,但又想回過頭,來看此文件剛才改動哪些內容的場景;比如下圖中是我剛才新建了一個diff.php文件,并且已經添加到暫存區,如下圖執行了git status命令結果所示:
但我突然發現,我已經忘記這個文件里到底有哪些內容被改變了,于是我使用了git diff diff.php命令查看變動的內容,執行結果如下圖所示:
在 Git 的返回信息中卻無法看到修改詳情,原因是因為 diff.php 文件被提交到暫存區之后,工作區并沒有再次改動,此時工作區與暫存區一致,當然就不能看出改動情況了。
這個時候,如果想要看diff.php文件里面修改了什么內容,就不是再把工作區和暫存區進行對比了,而是需要把暫存區與版本庫最近一次 commit 的內容進行比較,參考命令如下:
git diff --cached diff.php
命令執行結果如下圖所示
在圖中可以看出,diff.php 中新增了一行代碼,內容為lisi 。
6.4 與指定記錄比較
有些時候,我們可能需要代碼和歷史的某一個版本進行比較,這個時候你可以先通過git log命令,找到歷史提交記錄的一個 hash 值,如下圖所示:
6.4.1 工作區比較
將要比較的 hash 值復制下來,然后執行如下所示命令:
git diff hash值
在上圖中,可以看到工作區和指定記錄存在的差異。
6.4.2 暫存區比較
有些時候,我們想把暫存區的改動和指定記錄進行對比,那么在命令中加入--cached 即可,參考命令如下:
git diff --cached hash值
執行結果如下圖所示:
從圖中可以看到 diff.php 文件,在指定的版本還未存在,在當前的暫存區中被添加了進來,新增的內容有一行,內容是lisi。
6.5 與最新版本庫比較
很多時候,我們只需要將未正式提交的代碼(包含工作區與暫存區)與最新的 commit 記錄進行比較,雖然也可以通過指定 commit 的 hash 值進行,但是卻很不方便,需要先獲取到 hash 值,這里介紹一個簡單的方法,可以通過git diff HEAD命令方式快速對比,參考命令如下:
git diff HEAD
執行命令返回結果如下:
在執行的命令中,HEAD指的是當前所在的分支名,如果你想比較其他分支也可以將 HEAD 改成其他分支名。
6.6 比較兩個歷史記錄
有時候,可能會需要查看某一次提交記錄修改了什么內容,這個時候就需要將兩個歷史記錄進行比較;首先通過git log命令獲取到需要查看的記錄 hash 值,然后再找到這個記錄的上一個版本的 hash 值,拼接的參考命令如下所示:
git diff hash值1 hash值2
命令執行之后,顯示的效果如下:
6.7 小結
在這節內容中,主要介紹了工作區和暫存區的概念,以及如何使用diff命令進行比較差異,主要知識點有以下:
工作區,是指目前改動的內容還未使用git add臨時存儲
暫存區,是指改動的內容已經臨時存儲,還未正式通過git commit提交
比較修改的命令為git diff,不同情況增加不同參數
查看暫存區的額外參數為--cached
比較歷史差異輸入一個 hash 值,則是把當前的改動和歷史差異對比,兩個 hash 值則是把前一個版本和后面一個版本進行對比
如何寫好設計文檔
一份好的設計文檔需要提供清晰的問題描述、整體的概要設計、涵蓋各個細節的詳細設計等。
這篇有趣的英文小短文通過一個簡單的小例子介紹了Google工程師是怎么寫設計文檔的。本文為中文翻譯。原文鏈接如下:
寫文檔是我在谷歌學到的最重要的技能之一。在谷歌,文檔被用來討論問題、作為真實的信息源、組織知識。在我工作過的其他公司中,沒有一家對如何使用文檔進行協作有這樣深刻的理解。
這篇文章就是關于我在谷歌如何寫設計文檔的一個例子,這是一個真實的項目,用于在新冠疫情期間控制健身房現場人數。即使在新冠疫情結束后不需要預約健身房了,也可以訪問GitHub上的源代碼[1]。為了讓這篇文章更有趣,現在每個人都可以在谷歌文檔[2]上進行評論,而且谷歌文檔的格式也比Medium支持的要好。
01 問題描述
在新冠疫情期間,要求健身房控制現場會員總數,要求會員在去健身房之前先在網站上預訂。預約需要提前兩天,從午夜開始。例如,2021年04月01日的預訂將在當地時間2021年03月30日00:00 AM開放。
這個健身房里的游泳池提供的位置非常有限。我嘗試了好幾次,都沒能預定到早上6點的時間,后來工作人員告訴我,由于需求量很大,必須在午夜預訂。但是熬夜到半夜會打亂我的生物鐘,所以我沒法接受。
而且我覺得雇人做這件事也很不好,因為在內心深處,我認為早睡是健康高效生活方式的核心習慣,用金錢剝奪別人的好習慣是不道德的。在被告知沒有別的辦法之后,我決定寫一個程序來為我做預訂。
我個人認為用機器人來做工作是對別人的不公平,所以我對這個決定一點兒也沒感到自豪。相反,我認為健身房應該提高一些場地的價格。但這顯然超出了設計文檔的范圍,而且是非常主觀的想法。
02 需求
不在考慮范圍內:
03 概要設計瀏覽器自動化 vs 模擬請求
瀏覽器自動化是指通過程序來控制真實的瀏覽器,并在GUI上自動化操作。模擬請求是指讓程序通過HTTP與服務器交互,這個程序就像是一個Web瀏覽器(而不是控制一個瀏覽器)。
考慮到下面幾點,我認為瀏覽器自動化比模擬請求更好:
顯然利大于弊。
系統概述
image-253465
[3]是一個提供瀏覽器自動化解決方案的軟件庫。我們的程序將用Python編寫,并通過Python API控制,則通過它的Gecko驅動程序控制Firefox。
[4]是一個阻止操作系統進入睡眠狀態的程序。如果系統休眠,程序將無法在半夜運行。
04 詳細設計用戶輸入
用戶名、密碼、日期等都是從命令行參數中輸入的。
重試
程序將捕獲所有異常(頁面未加載等)并重試100次直到預訂成功,成功的預訂通過確認DOM元素進行識別。
瀏覽器選擇
我們需要使用主流瀏覽器之一。我考慮并測試了Chrome、Firefox和Safari,Safari和Chrome都需要額外的步驟來使用相應的驅動程序,所以我選擇了Firefox。它也需要一些來自操作系統設置的認證,但只需要在最初幾次確認就可以了。
日志
程序自動執行瀏覽器操作,就像是由用戶發起的一樣。本質上,它將在循環中執行以下操作:
查找某個元素對元素進行操作(輸入文本、選擇選項或單擊)等待預期結果,然后返回1
因此,每個日志記錄將有兩項內容:
這樣的日志記錄將使調試變得容易。
保持電腦持續運行
如果操作系統在程序啟動到午夜之間進入休眠狀態,則程序在午夜就無法運行了,可以防止這種情況發生。它是一個命令行工具,我們在Python中把它作為子進程啟動:
subprocess.Popen([‘caffeinate’, ‘-d’, ‘-w’, ‘%d’ % os.getpid()])
定位控制
提供了一組方法[5]來訪問特定的DOM元素,其中xpath的表達能力最強。因此,我們將使用h來定位DOM元素,如按鈕、輸入框等。
只要有可能,我們寧愿依賴DOM的內部文本來定位它們。相對于DOM結構和屬性(類名等),內部文本的優勢并不是說它不太可能更改,而是如果它們發生更改,更容易調試。當然,我們必須對DOM結構做一些假設,比如我們需要點擊class='control'分區(div)下的class='logon'的第二個按鈕。
等待頁面加載
在發送每個HTTP請求后,程序需要等待加載頁面(通常是2~5秒,是的,這個站點很慢)。這是由 API[6]完成的。例如,以下代碼將等待120秒,直到 被加載并成為可被點擊的按鈕。
book_btn = WebDriverWait(driver, 120).until(EC.element_to_be_clickable((By.XPATH, “//button[@ng-reflect-router-link=’/Appointments’]”)))
如果按鈕在120秒內加載失敗,將引發異常。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。