簡體   English   中英

git:當前分支和分支創建之間的差異

[英]git: diff between current branch and branch creation

想象一下:

git-diff-三點

我三天前創建了分支“B”。 這是我目前正在處理的分支。 現在我想知道自從創建分支( X )以來發生了什么變化。

這給了我 B 和 X 之間的差異(如圖片中的虛線):

git diff A...

上面的命令很方便,因為它很短而且我不需要記住“X”。

但是:我超級懶。 我不想記住我當前的分支是從哪個分支創建的。

我怎樣才能避免記住/輸入A

我正在尋找一種不需要我這邊輸入的方法。 它應該列出自上次創建分支以來的所有更改。

好吧, @{-1}可能是 A。但話又說回來,它也可能不是。 它只是意味着“我以前所在的分支”。 同樣,查看git reflog可能會讓您推斷出創建當前分支時所處的位置。

但是當前分支本身並沒有告訴你任何這些。 這里真正的問題是你對“分支”的理解與 Git 不同。 “因為分支被創建”這句話可能會誤導你。

你似乎認為 B 是“從 X 到 B 結束的所有東西”。 不是。 B 只是一次提交:圖中標記為 B 的提交。 從那之后向后的所有其他內容——B 之前的提交,之前的提交,以及 X,以及 X之前的提交,以及之前的提交,一直向后到根提交——具有完全相同的狀態。 它們是可從 B 訪問的提交,僅此而已。

所以在 Git 心目中 X 並沒有什么特別之處。 認為它很特別,因為它是 A 和 B “相遇”的地方。 但是要區分這個事實,您必須知道 BA 的名稱。您看到的是一個依賴於 A 的拓撲; 如果你想讓 Git 幫助你,你必須將你看到的內容傳達給 Git。

一旦你願意談論 A 和 B,那么很好,你可以要求git diff ...Agit diff A...找出自 X 以來發生了什么變化。或者你可以談論git merge-base AB找到X。但只有人類才能分辨出這里的關鍵是A。

但是:我超級懶。 我不想記住我當前的分支是從哪個分支創建的。

然后你需要在一個名為git-diffca的可執行文件中編寫腳本,然后可以將其稱為git diffca (ca 代表“共同祖先”)

在該腳本中,您需要決定要在所有候選分支中選擇什么標准:

     c--c--c     (C)
    /
a--Y--X--a--a    (A)
       \
        b--b--b  (B, HEAD)
     

您想看什么:來自Y (分支CB之間的共同祖先)的變化? 或來自X (在AB之間)

我會查看所有分支,為每個分支計算git merge-base <aBranch> B ,並獲取最近的提交(在架構的情況下為X

然后腳本將顯示git diff A... (因為git merge-base AB產生了與 B 的最新共同祖先)

我不想記住我當前的分支是從哪個分支創建的。 我怎樣才能避免記住/輸入A

告訴 Git 為您跟蹤它。 為了實現這一點,當您想從當前結帳中分支出來時,請添加t選項:

git checkout -tb B

將切換到一個新的分支B跟蹤您現有的......任何分支, A ,對吧? 請注意,我不必記住或鍵入它。 事后查看git branch -u選項以設置新的上游。

當您告訴 git 您要跟蹤的分支時, git diff @{u}...git diff @{upstream}...完全符合您的要求。 您甚至可以將其git config --global alias.du diff @{u}...別名, git config --global alias.du diff @{u}...


請注意,Git 通常會自動從遙控器設置對上游分支的跟蹤:如果您說git checkout fix32943並且您沒有fix32943分支並且正好有一個帶有fix32943分支的遙控器,Git 將創建一個本地fix32943分支並進行設置,就好像您已經完成了上述操作,因為這正是它為您所做的,以跟蹤上游。 所以git diff @{U}...通常已經按照你想要的方式工作了。

我將重復@matt 在他的回答中詳細說明的內容: git跟蹤提交,但不跟蹤分支


然而,有些東西看起來像“那個分支的生命”,它是那個分支的 reflog :

git reflog my/branch

您可以檢查歷史記錄,看看是否在那里找到了任何信息。

例如:創建分支時的提交將是:

git reflog my/branch | tail -1
  # and use something like `| awk '{ print $1 }'` for the sha,
  # or parse the 'branch: Created from ...' message (if there is one)
  # to see if there is a branch name

git reflog --format="%H" my/branch | tail -1   # if you want only the sha

但同樣有警告:如果您在分支的生命周期內運行了git rebase ,那么初始提交可能不再是您正在尋找的分叉點。


另一個代理可能是:查看分支B的歷史記錄中的提交,以及沒有其他分支的歷史記錄:

# the following will list all branches except 'my/branch' :
git branch --format="%(refname:short)" | grep -v "my/branch"

# here is a way to list all commits on 'my/branch', excluding commits
# from all other branches.
# Adding `--boundary` will also display the first 'hidden' commit
git log --boundary --oneline --graph my/branch --not $(<the command above>)

# you can also replace 'git log' with 'git rev-list', if you only want the hashes

幸運的是,作為邊界提到的提交就是您正在尋找的提交。
需要注意的是:如果你的分支歷史中有一些合並,你可能有幾個“邊界”點,如果有另一個分支比你正在尋找的X最近從 B“分叉”,那么邊界將是該分支的分叉點,而不是masterdevelop


根據您的評論更新:您可以

  • 列出本地克隆中的所有功能分支(除了您自己的分支)
  • 從這些分支中的任何一個中查找當前分支的“分叉點”
# get the name of your current active branch :
mybranch=$(git rev-parse --abbrev-ref HEAD)

# make a separate function to list on stdout "all the branches except mine"
list_branches () {
  # list the `master` branch
  echo "master"

  # get all 'origin/somefeature' branches, excluding mybranch

  # suggestion: list remote branches (you will get all features,
  # even if you haven't created a local checkout of a branch)
  git branch -r --format="%(refname:short)" |\
    grep "/feat/" |\    # you can grep for a pattern if you have one
    grep -b "$mybranch" # remove your branch from the lot
}

# get the 'boundary' commits of your branch with respect to
# all the other branches
base=$(
  git rev-list --boundary --graph "$mybranch" --not $(list_branches "$mybranch") |\
    grep -e "^-" |\  # rev-list will prefix boundary commits with a '-'
    tail -1 |\       # if there are several, only take the last one
    tr -d '-'        # delete that leading '-'
)

# with some luck, we computed the correct base commit :
git diff $base...

正如我之前的每個人已經說過的, git跟蹤提交而不是分支。 您可以在從中分支之前標記提交以使其更容易,但這仍然需要您手動進行標記。

腳步:

  • git tag <some descriptive tag>
  • git push origin <tag name>如果是單個標簽
    • git push --tags用於多個標簽

然后從這里您可以輕松查看日志並根據需要查看更改。

或者您可以將您的分支命名為branchName_branchedFrom類型的命名約定,然后它會更容易跟蹤(branchedFrom 可能是短 sha1,或者如果您已標記它,則可能是標簽名稱。

事后不可能(並且做git diff A...是最好和最短的選擇)。 但是,如果您事先知道一個分支位於另一個分支的上游,則可以在使用-t / --track選項創建分支時設置“上游配置”:

git checkout --track --branch newbranch upstreambranch

要為現有分支配置上游,請使用帶有-u / --set-upstream-to=選項的git branch命令:

git branch --set-upstream-to=upstreambranch existingbranch

(在您的示例中:newbranch/existingbranch == C,upstreambranch = A)

然后,您可以使用newbranch@{upstream}newbranch@{u}來訪問上游分支的當前分支提示提交。 要獲得當前分支( HEAD )的上游, @{u}就足夠了。

然后你的命令變成:

git diff newbranch@{u}...newbranch

或者,簽出新newbranch

git diff @{u}...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM