Làm thế nào để tìm cha mẹ gần nhất của chi nhánh Git?


419

Giả sử tôi có kho lưu trữ cục bộ sau với cây cam kết như thế này:

master --> a
            \
             \
      develop c --> d
               \
                \
         feature f --> g --> h

masterlà tôi đây là mã phát hành ổn định mới nhất , developlà tôi đây là 'bên cạnh' mã phát hành , và featuremột tính năng mới được chuẩn bịdevelop .

Những gì tôi muốn có thể thực hiện trên repo từ xa của mình bằng cách sử dụng các móc, là để đẩy featurebị từ chối trừ khi cam kết flà hậu duệ trực tiếp của developHEAD. tức là cây cam kết trông như thế này vì tính năng đã được git rebasebật d.

master --> a
            \
             \
      develop c --> d
                     \
                      \
               feature f --> g --> h

Vì vậy, nó có thể:

  • Xác định nhánh cha mẹ của feature?
  • Xác định các cam kết trong nhánh cha mẹ flà hậu duệ của?

Từ đó tôi sẽ kiểm tra xem phần đầu của nhánh cha là gì và xem liệu phần ftrước có khớp với phần gốc của phần gốc hay không, để xác định xem tính năng này có cần phải được khởi động lại không.


câu hỏi này nên được đọc lại để tìm cha mẹ của cha mẹ.
Tim Boland

Câu trả lời:


348

Giả sử rằng kho lưu trữ từ xa có một bản sao của nhánh phát triển (mô tả ban đầu của bạn mô tả nó trong một kho lưu trữ cục bộ, nhưng có vẻ như nó cũng tồn tại trong điều khiển từ xa), bạn sẽ có thể đạt được những gì tôi nghĩ bạn muốn, nhưng cách tiếp cận là một chút khác biệt với những gì bạn đã hình dung.

Lịch sử của Git dựa trên DAG cam kết. Các chi nhánh (và các lượt giới thiệu khác nói chung) chỉ là các nhãn tạm thời chỉ ra các cam kết cụ thể trong DAG cam kết tăng trưởng liên tục. Như vậy, mối quan hệ giữa các nhánh có thể thay đổi theo thời gian, nhưng mối quan hệ giữa các cam kết thì không.

    ---o---1                foo
            \
             2---3---o      bar
                  \
                   4
                    \
                     5---6  baz

Có vẻ như bazlà dựa trên (một phiên bản cũ) bar? Nhưng nếu chúng ta xóa barthì sao?

    ---o---1                foo
            \
             2---3
                  \
                   4
                    \
                     5---6  baz

Bây giờ có vẻ như bazlà dựa trên foo. Nhưng tổ tiên của bazkhông thay đổi, chúng tôi chỉ xóa một nhãn (và kết quả là cam kết lơ lửng). Và nếu chúng ta thêm một nhãn mới tại 4?

    ---o---1                foo
            \
             2---3
                  \
                   4        quux
                    \
                     5---6  baz

Bây giờ có vẻ như bazlà dựa trên quux. Tuy nhiên, tổ tiên không thay đổi, chỉ có nhãn thay đổi.

Tuy nhiên, nếu chúng tôi hỏi rằng Cam có phải 6là hậu duệ của cam kết 3không? (giả sử 36có đầy đủ tên cam kết SHA-1), thì câu trả lời sẽ là có đúng, có hay không barvà có quuxnhãn hay không.

Vì vậy, bạn có thể đặt câu hỏi như là cam kết được đẩy ra là hậu duệ của đầu phát triển hiện tại của chi nhánh phát triển ? Nhưng, bạn không thể tin cậy hỏi rằng nhánh cha mẹ của cam kết bị đẩy là gì?

Một câu hỏi chủ yếu đáng tin cậy dường như gần với những gì bạn muốn là:

Đối với tất cả các tổ tiên của cam kết được đẩy (không bao gồm mẹo phát triển hiện tại và tổ tiên của nó), có mẹo phát triển hiện tại với tư cách là cha mẹ:

  • có ít nhất một cam kết như vậy tồn tại?
  • tất cả các cam kết như vậy cam kết cha mẹ đơn?

Mà có thể được thực hiện như:

pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
    echo "'$basename' is missing, call for help!"
    exit 1
fi
parents_of_children_of_base="$(
  git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
  grep -F "$baserev"
)"
case ",$parents_of_children_of_base" in
    ,)     echo "must descend from tip of '$basename'"
           exit 1 ;;
    ,*\ *) echo "must not merge tip of '$basename' (rebase instead)"
           exit 1 ;;
    ,*)    exit 0 ;;
esac

Điều này sẽ bao gồm một số những gì bạn muốn hạn chế, nhưng có thể không phải là tất cả.

Để tham khảo, đây là một lịch sử ví dụ mở rộng:

    A                                   master
     \
      \                    o-----J
       \                  /       \
        \                | o---K---L
         \               |/
          C--------------D              develop
           \             |\
            F---G---H    | F'--G'--H'
                    |    |\
                    |    | o---o---o---N
                     \   \      \       \
                      \   \      o---o---P
                       \   \   
                        R---S

Đoạn mã trên có thể được sử dụng để từ chối HSkhi chấp nhận H', J, K, hoặc N, nhưng nó sẽ cũng chấp nhận LP(họ liên quan đến sáp nhập, nhưng họ không hợp nhất là đỉnh của phát triển ).

Để từ chối LP, bạn có thể thay đổi câu hỏi và hỏi

Đối với tất cả các tổ tiên của cam kết đẩy (không bao gồm mẹo phát triển hiện tại và tổ tiên của nó):

  • Có bất kỳ cam kết với hai cha mẹ?
  • nếu không, ít nhất một cam kết như vậy có mẹo phát triển (chỉ) cha mẹ hiện tại của nó không?
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
    echo "'$basename' is missing, call for help!"
    exit 1
fi
parents_of_commits_beyond_base="$(
  git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
  grep -v '^commit '
)"
case "$parents_of_commits_beyond_base" in
    *\ *)          echo "must not push merge commits (rebase instead)"
                   exit 1 ;;
    *"$baserev"*)  exit 0 ;;
    *)             echo "must descend from tip of '$basename'"
                   exit 1 ;;
esac

Tôi nhận được điều này: git: fatal: đối số mơ hồ '...': cả sửa đổi và tên tệp. ý định ba chấm là gì?
Jack Ukleja

1
@Schneider Tôi khá chắc chắn rằng '...' được dự định là người giữ chỗ trong ví dụ này: nếu bạn thay thế nó bằng SHA của cam kết bạn đang cố gắng thực hiện kiểm tra này (giả sử, người đứng đầu chi nhánh bạn hiện đang ở trên), mọi thứ hoạt động tốt.
Daniel Brady

Cảm ơn câu trả lời công phu này! Nó là siêu hữu ích. Tôi muốn tạo một hook tương tự, nhưng tôi không muốn mã hóa tên của nhánh phát triển. Có nghĩa là tôi muốn một cái móc để ngăn chặn rebase đến một nhánh khác ngoài nhánh cha. Nếu tôi hiểu rõ câu trả lời của bạn (tôi mới biết về bash và những thứ khác) thì điều này không có trong câu trả lời của bạn, phải không? Có cách nào để làm việc này không?
Kemeia

Bạn có sẵn sàng trả lời một câu hỏi liên quan? Tôi không thể lấy mã của bạn để làm việc trên kho lưu trữ XÓA. Dưới đây là liên kết cho câu hỏi tiếp theo về làm thế nào để thích nghi với cách tiếp cận của bạn để làm việc với một kho REMOTE: stackoverflow.com/questions/49619492/...
CodeMed

Điều này đã không làm việc cho tôi khi tôi có develop > release > feature, tôi sẽ phát triển trở lại và nó đòi hỏi phải biết cha mẹ. Giải pháp cho vấn đề của tôi là stackoverflow.com/a/56673640/2366390
động từ

241

Một lời khiển trách

Một cách khác để diễn đạt câu hỏi là "Cam kết gần nhất cư trú trên một nhánh không phải là chi nhánh hiện tại và đó là chi nhánh nào?"

Một giải pháp

Bạn có thể tìm thấy nó với một chút ma thuật dòng lệnh

git show-branch \
| sed "s/].*//" \
| grep "\*" \
| grep -v "$(git rev-parse --abbrev-ref HEAD)" \
| head -n1 \
| sed "s/^.*\[//" 

Với awk :

git show-branch -a \
| grep '\*' \
| grep -v `git rev-parse --abbrev-ref HEAD` \
| head -n1 \
| sed 's/[^\[]*//' \
| awk 'match($0, /\[[a-zA-Z0-9\/-]+\]/) { print substr( $0, RSTART+1, RLENGTH-2 )}'

Đây là cách nó hoạt động:

  1. Hiển thị một lịch sử văn bản của tất cả các cam kết, bao gồm các chi nhánh từ xa.
  2. Tổ tiên của cam kết hiện tại được chỉ định bởi một ngôi sao. Lọc ra mọi thứ khác.
  3. Bỏ qua tất cả các cam kết trong chi nhánh hiện tại.
  4. Kết quả đầu tiên sẽ là nhánh tổ tiên gần nhất. Bỏ qua các kết quả khác.
  5. Tên chi nhánh được hiển thị [trong ngoặc]. Bỏ qua mọi thứ bên ngoài dấu ngoặc và dấu ngoặc.
  6. Đôi khi, tên chi nhánh sẽ bao gồm một ~ # hoặc ^ # để cho biết có bao nhiêu lần xác nhận giữa cam kết được tham chiếu và đầu nhánh. Chúng tôi không quan tâm. Mặc kệ họ.

Và kết quả

Chạy mã trên

 A---B---D <-master
      \
       \
        C---E---I <-develop
             \
              \
               F---G---H <-topic

Sẽ cung cấp cho bạn developnếu bạn chạy nó từ H và masternếu bạn chạy nó từ I.

Mã có sẵn như là một ý chính


24
Đã xóa một backtick trailing gây ra lỗi. Khi chạy lệnh này, tôi nhận được một số lượng lớn các cảnh báo, phàn nàn về từng chi nhánh nóicannot handle more than 25 refs
Jon L.

1
@JoeChrysler bạn có nghĩ rằng bạn có thể tạo một dòng thay vì 2 và có thể làm cho nó hoạt động trên Mac như ackkhông có sẵn trên Mac (có người đề nghị thay thế ackbằng grep)
phân cực

53
Xin lỗi, đó là một sai. Đây là một trong những chính xác làm việc cho tôi:git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'
droidbot

15
@droidbot Đẹp, nhưng cần sắp xếp lại đường ống để tránh xóa ref khi grep -v bắt thông điệp cam kết hoặc tên chi nhánh của bạn là một phần của tên chi nhánh khác. git show-branch | sed "s/].*//" | grep "\*" | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed "s/^.*\[//"
gaal

3
@OlegAbrazhaev Tôi không biết bạn đã trả lời câu hỏi chưa. sử dụng bí danh git của: parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"làm việc cho tôi
mduttondev

111

Bạn cũng có thể thử:

git log --graph --decorate

5
git log --graph --decorate --simplify-by-decorationở đâu --graphlà tùy chọn.
Na13-c

1
git log --graph --decorate --simplify-by-decoration --oneline
anishtain4

106

cha mẹ

Bạn chỉ có thể chạy lệnh

git parent

để tìm cha mẹ của chi nhánh, nếu bạn thêm câu trả lời của @Joe Chrysler dưới dạng bí danh git . Nó sẽ đơn giản hóa việc sử dụng.

Mở tệp gitconfig tại "~/.gitconfig"bằng cách sử dụng bất kỳ trình soạn thảo văn bản. (Đối với linux). Và đối với Windows, đường dẫn ".gitconfig" thường nằm ởc:\users\your-user\.gitconfig

vim  ~/.gitconfig

Thêm lệnh bí danh sau trong tệp:

[alias]
            parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"

Lưu và thoát khỏi trình soạn thảo.

Chạy lệnh git parent

Đó là nó!


5
Đây là một giải pháp tuyệt vời. Nó cũng sẽ hữu ích để thêm một số đầu ra mẫu để được đảm bảo về kết quả mong đợi. Khi tôi chạy nó, tôi đã nhận được một vài cảnh báo trước dòng cuối cùng mà tôi tin là tên của nhánh mẹ.
ttemple

4
Hoạt động như một lá bùa! Đối với người dùng windows, .gitconfig thường được đặt tại c: \ users \ your-user \ .gitconfig
zion

12
Lấy cannot handle more than 25 refsngoại lệ.
shajin

ai đó có thể chỉnh sửa điều này để xử lý cảnh báo? @ttemple, bạn có thể không?
NIKHIL CM

@NIKHILCM hoạt động như một Quán quân. Nhưng tôi có một câu hỏi ở đây liệu phụ huynh cho biết chi nhánh được tạo ra từ đâu hay cái gì khác?
Hariprasath

52

Tôi có một giải pháp cho vấn đề tổng thể của bạn (xác định xem featurecó phải xuất phát từ mẹo hay không develop), nhưng nó không hoạt động bằng phương pháp bạn đã vạch ra.

Bạn có thể sử dụng git branch --containsđể liệt kê tất cả các nhánh đi xuống từ đầu develop, sau đó sử dụng grepđể đảm bảo featurenằm trong số đó.

git branch --contains develop | grep "^ *feature$"

Nếu nó nằm trong số đó, nó sẽ in " feature"ra đầu ra tiêu chuẩn và có mã trả về là 0. Nếu không, nó sẽ không in gì và có mã trả về là 1.


1
Điều này hoạt động nhưng cần lưu ý rằng nó có thể mất nhiều thời gian trên một kho lưu trữ có rất nhiều ref. Điều đó làm cho nó ít hơn một chút so với lý tưởng để chạy trong, ví dụ, một móc nhận trước.
ebneter

Tôi đang tìm chi nhánh, chúng tôi sẽ gọi nó <branch>, nơi tôi thực hiện: git checkout -b <branch-2>từ ... ĐÂY là câu trả lời! Không cần grep, thực sự. git branch --contains <branch>
Poopy McFartnoise 17/07/19

44

Điều này làm việc tốt cho tôi.

git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'

Câu trả lời lịch sự từ: @droidbot và @Jistanidiot


Vâng, nhưng đôi khi nó khiến bạn "vỡ ống" từ grep.
Vladislav Rastrusny

1
*không phải là một regex thích hợp để vượt qua grep. Nên sử dụng grep -F '*'hoặc grep '\*'thay thế. Giải pháp tốt khác.
thân

Tôi không có đầu ra.
Sandip Subedi

làm việc cho tôi ....
roottraveller

11

Vì không có câu trả lời nào ở trên hoạt động trên kho lưu trữ của chúng tôi, tôi muốn chia sẻ theo cách riêng của mình, sử dụng các kết hợp mới nhất trong git log:

#!/bin/bash
git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 10

Đặt nó trong một tập lệnh có tên git-last-merges, cũng chấp nhận một tên nhánh làm đối số (thay vì nhánh hiện tại) cũng như các tập lệnh khácgit log đối số

Từ đầu ra, chúng ta có thể phát hiện thủ công các nhánh mẹ dựa trên các quy ước phân nhánh riêng và số lần hợp nhất từ ​​mỗi nhánh.

EDIT: Nếu bạn git rebasethường xuyên sử dụng trên các nhánh con (và các phép hợp nhất được chuyển tiếp nhanh thường xuyên nên không có quá nhiều cam kết hợp nhất), câu trả lời này sẽ không hoạt động tốt, vì vậy tôi đã viết một kịch bản để đếm trước các cam kết (bình thường và hợp nhất) và đằng sau các cam kết (không nên có bất kỳ sự hợp nhất nào phía sau trong nhánh mẹ) trên tất cả các nhánh so với nhánh hiện tại. Chỉ cần chạy tập lệnh này và cho tôi biết nếu làm việc cho bạn hay không

#!/bin/bash
HEAD="`git rev-parse --abbrev-ref HEAD`"
echo "Comparing to $HEAD"
printf "%12s  %12s   %10s     %s\n" "Behind" "BehindMerge" "Ahead" "Branch"
git branch | grep -v '^*' | sed 's/^\* //g' | while read branch ; do
    ahead_merge_count=`git log --oneline --merges $branch ^$HEAD | wc -l`
    if [[ $ahead_merge_count != 0 ]] ; then
        continue
    fi
    ahead_count=`git log --oneline --no-merges $branch ^$HEAD | wc -l`
    behind_count=`git log --oneline --no-merges ^$branch $HEAD | wc -l`
    behind_merge_count=`git log --oneline --merges ^$branch $HEAD | wc -l`
    behind="-$behind_count"
    behind_merge="-M$behind_merge_count"
    ahead="+$ahead_count"
    printf "%12s  %12s   %10s     %s\n" "$behind" "$behind_merge" "$ahead" "$branch"
done | sort -n

Cảm ơn. Mặc dù điều này có thể không hoạt động tốt nếu bạn sử dụng rebasethường xuyên (và hợp nhất là fast-forwarded thường xuyên). Tôi sẽ chỉnh sửa câu trả lời của mình nếu tôi tìm thấy giải pháp tốt hơn.
saeedgnu

1
Duy nhất? trả lời cho đến nay mà làm việc hợp lý cho tôi trong trường hợp chi nhánh hiện tại là chủ. Hầu hết các giải pháp khác đã cho một kết quả ngẫu nhiên (và rõ ràng không chính xác) trong trường hợp cạnh được thừa nhận này khi không có nhánh cha thực tế.
thân

Đây là câu trả lời duy nhất làm việc cho tôi. Để có được cha mẹ đầu tiên thay vì danh sách 10 người đầu tiên, bạn có thể sử dụng mục này: git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 1 | cut -d ' ' -f 8
lots0logs

10

Một giải pháp

Giải pháp dựa trêngit show-branch không hoàn toàn hiệu quả với tôi (xem bên dưới), vì vậy tôi đã kết hợp nó với giải pháp dựa trêngit log và kết thúc với điều này:

git log --decorate --simplify-by-decoration --oneline \ # selects only commits with a branch or tag
      | grep -v "(HEAD" \                               # removes current head (and branch)
      | head -n1 \                                      # selects only the closest decoration
      | sed 's/.* (\(.*\)) .*/\1/' \                    # filters out everything but decorations
      | sed 's/\(.*\), .*/\1/' \                        # picks only the first decoration
      | sed 's/origin\///'                              # strips "origin/" from the decoration

Hạn chế và hãy cẩn thận

  • Có thể tách rời ĐẦU (nhiều công cụ CI làm như vậy để đảm bảo chúng xây dựng cam kết chính xác trong một nhánh nhất định), nhưng nhánh gốc và nhánh cục bộ phải ngang bằng hoặc "trên" đầu hiện tại.
  • Không được có thẻ theo cách này (tôi đoán; tôi chưa kiểm tra tập lệnh trên các cam kết với một thẻ giữa nhánh con và nhánh cha)
  • kịch bản dựa trên thực tế "ĐẦU" luôn được liệt kê là trang trí đầu tiên củalog lệnh
  • chạy tập lệnh trên masterdevelop kết quả (chủ yếu) trong<SHA> Initial commit

Kết quả

 A---B---D---E---F <-origin/master, master
      \      \
       \      \
        \      G---H---I <- origin/hotfix, hotfix
         \
          \
           J---K---L <-origin/develop, develop
                \
                 \
                  M---N---O <-origin/feature/a, feature/a
                       \   \
                        \   \
                         \   P---Q---R <-origin/feature/b, feature/b
                          \
                           \
                            S---T---U <-origin/feature/c, feature/c

Mặc dù sự tồn tại của chi nhánh địa phương (ví dụ: chỉ origin/topiccó mặt vì cam kết Ođã được kiểm tra trực tiếp bởi SHA của nó), tập lệnh sẽ được in như sau:

  • Đối với cam kết G, H,I (chi nhánh hotfix) →master
  • Đối với cam kết M, N,O (chi nhánh feature/a) →develop
  • Đối với cam kết S, T,U (chi nhánh feature/c) →develop
  • Đối với cam kết P, Q,R (chi nhánh feature/b) →feature/a
  • Đối với cam kết J, K, L(chi nhánh develop) → <sha> Initial commit*
  • Đối với cam kết B, D, E, F(chi nhánh master) →<sha> Initial commit

* - hoặc masternếu developcác cam kết của bạn nằm trên đầu của Master (~ chủ sẽ có thể chuyển tiếp nhanh để phát triển)


Tại sao không hiển thị chi nhánh làm việc cho tôi

Giải pháp dựa trêngit show-branch đã chứng minh không đáng tin cậy đối với tôi trong các tình huống sau:

  • ĐẦU tách ra - bao gồm cả trường hợp đầu tách rời có nghĩa là thay thế grep '\*' \cho 'grep'! ' \ - và đó chỉ là khởi đầu của mọi rắc rối
  • chạy tập lệnh trên masterdevelop kết quả developtương ứng và ``
  • các nhánh trênmaster nhánh ( hotfix/nhánh) kết thúc với developtư cách là cha mẹ vì masternhánh cha gần nhất của chúng được đánh dấu !thay vì *lý do.

2
Chỉ có câu trả lời có hiệu quả - như một bí danh git:"!git log --decorate --simplify-by-decoration --oneline | grep -v '(HEAD' | head -n1 | sed 's/.* (\\(.*\\)) .*/\\1/' | sed 's/\\(.*\\), .*/\\1/' | sed 's/origin\\///'"
Ian Kemp

8

Hãy nhớ rằng, như được mô tả trong "Git: Tìm chi nhánh mà một cam kết đến từ đâu" , bạn không thể dễ dàng xác định chi nhánh nơi cam kết đó được thực hiện (các chi nhánh có thể được đổi tên, di chuyển, xóa ...), mặc dù đó git branch --contains <commit>là một sự khởi đầu.

  • Bạn có thể quay lại từ cam kết để cam kết cho đến khi git branch --contains <commit>không liệt kê featurechi nhánh và danh sách developchi nhánh,
  • so sánh cam kết SHA1 với /refs/heads/develop

Nếu hai cam kết id khớp nhau, bạn tốt để đi (điều đó có nghĩa là featurechi nhánh có nguồn gốc ở đầu của develop).


6

Ma thuật dòng lệnh của JoeChrysler có thể được đơn giản hóa. Đây là logic của Joe - để đơn giản, tôi đã giới thiệu một tham số có tên cur_branchthay thế lệnh thay thế `git rev-parse --abbrev-ref HEAD`cho cả hai phiên bản; có thể được khởi tạo như vậy:

cur_branch=$(git rev-parse --abbrev-ref HEAD)

Sau đó, đây là đường ống của Joe:

git show-branch -a           |
  grep '\*'                  | # we want only lines that contain an asterisk
  grep -v "$cur_branch"      | # but also don't contain the current branch
  head -n1                   | # and only the first such line
  sed 's/.*\[\(.*\)\].*/\1/' | # really, just the part of the line between []
  sed 's/[\^~].*//'            # and with any relative refs (^, ~n) removed

Chúng ta có thể thực hiện điều tương tự như tất cả năm bộ lọc lệnh riêng lẻ đó trong một awklệnh tương đối đơn giản :

git show-branch -a |
  awk -F'[]^~[]' '/\*/ && !/'"$cur_branch"'/ {print $2;exit}'  

Điều đó bị phá vỡ như thế này:

-F'[]^~[]' 

tách dòng vào các lĩnh vực tại ], ^, ~, và [ký tự.

/\*/                      

Tìm các dòng có dấu hoa thị

&& !/'"$cur_branch"'/

... nhưng không phải tên chi nhánh hiện tại

{ print $2;               

Khi bạn tìm thấy một dòng như vậy, hãy in trường thứ hai của nó (nghĩa là phần giữa lần xuất hiện thứ nhất và lần thứ hai của các ký tự phân tách trường của chúng tôi). Đối với tên nhánh đơn giản, đó sẽ chỉ là những gì nằm giữa dấu ngoặc; đối với các ref có bước nhảy tương đối, nó sẽ chỉ là tên mà không cần sửa đổi. Vì vậy, bộ phân tách trường của chúng tôi xử lý ý định của cả hai sedlệnh.

  exit }

Sau đó thoát ra ngay lập tức. Điều này có nghĩa là nó chỉ xử lý dòng khớp đầu tiên, vì vậy chúng ta không cần phải đưa đầu ra qua head -n 1.


3
Lưu ý rằng một số nhánh có thể bị thiếu từ đầu ra do có quá nhiều ref. Thay vào đó, chúng được hiển thị như cảnh báo trên thiết bị lỗi chuẩn.
Zitrax

5

Dưới đây là triển khai PowerShell của giải pháp Mark Reed:

git show-branch -a | where-object { $_.Contains('*') -eq $true} | Where-object {$_.Contains($branchName) -ne $true } | select -first 1 | % {$_ -replace('.*\[(.*)\].*','$1')} | % { $_ -replace('[\^~].*','') }

5

Tôi không nói rằng đây là một cách tốt để giải quyết vấn đề này, tuy nhiên điều này có vẻ hiệu quả với tôi.

git branch --contains $(cat .git/ORIG_HEAD) Vấn đề là việc tạo ra một tệp đang nhìn trộm vào hoạt động bên trong của git vì vậy điều này không nhất thiết phải tương thích về phía trước (hoặc tương thích ngược).


3

Triển khai đa nền tảng với Ant

    <exec executable="git" outputproperty="currentBranch">
        <arg value="rev-parse" />  
        <arg value="--abbrev-ref" />  
        <arg value="HEAD" />  
    </exec>

    <exec executable="git" outputproperty="showBranchOutput">
        <arg value="show-branch" />  
        <arg value="-a" />  
    </exec>

    <loadresource property="baseBranch">
      <propertyresource name="showBranchOutput"/>
          <filterchain>
            <linecontains>
              <contains value="*"/>
            </linecontains>
            <linecontains negate="true">
              <contains value="${currentBranch}"/>
            </linecontains>
            <headfilter lines="1"/>
            <tokenfilter>
                <replaceregex pattern=".*\[(.*)\].*" replace="\1"/>
                <replaceregex pattern="[\^~].*" replace=""/>
            </tokenfilter>
          </filterchain>
    </loadresource>

    <echo message="${currentBranch} ${baseBranch}" />

2

@Mark Reed: Bạn nên thêm rằng dòng cam kết không chỉ chứa dấu hoa thị mà còn bắt đầu bằng dấu hoa thị! Mặt khác, các thông điệp cam kết có dấu hoa thị cũng được bao gồm trong các dòng khớp. Nên nó phải là:

git show-branch -a | awk -F'[]^~[]' '/^\*/ && !/'"$current_branch"'/ {print $2;exit}'

hoặc phiên bản dài:

git show-branch -a           |
  awk '^\*'                  | # we want only lines that contain an asterisk
  awk -v "$current_branch"   | # but also don't contain the current branch
  head -n1                   | # and only the first such line
  sed 's/.*\[\(.*\)\].*/\1/' | # really, just the part of the line between []
  sed 's/[\^~].*//'            # and with any relative refs (^, ~n) removed`

2
vbc=$(git rev-parse --abbrev-ref HEAD)
vbc_col=$(( $(git show-branch | grep '^[^\[]*\*' | head -1 | cut -d* -f1 | wc -c) - 1 )) 
swimming_lane_start_row=$(( $(git show-branch | grep -n "^[\-]*$" | cut -d: -f1) + 1 )) 
git show-branch | tail -n +$swimming_lane_start_row | grep -v "^[^\[]*\[$vbc" | grep "^.\{$vbc_col\}[^ ]" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'

Đạt được kết thúc giống như câu trả lời của Mark Reed, nhưng sử dụng một cách tiếp cận an toàn hơn nhiều mà không làm sai trong một số tình huống:

  1. Cam kết cuối cùng của nhánh mẹ là hợp nhất, làm cho cột hiển thị - không*
  2. Thông điệp cam kết chứa tên chi nhánh
  3. Thông điệp cam kết chứa *

0

Bất cứ ai cũng muốn làm điều này trong những ngày này - ứng dụng SourceTree của Atlassian cho bạn thấy một đại diện trực quan tuyệt vời về cách các chi nhánh của bạn liên quan đến nhau, tức là nơi họ bắt đầu và nơi họ hiện đang ngồi theo thứ tự cam kết (ví dụ: ĐẦU hoặc 4 cam kết, v.v.) .


0

Nếu bạn sử dụng Cây nguồn, hãy xem chi tiết cam kết của bạn> Cha mẹ> thì bạn sẽ thấy các số cam kết được gạch chân (liên kết)


0

Một thay thế: git rev-list master | grep "$(git rev-list HEAD)" | head -1

Nhận cam kết cuối cùng rằng đó là cả chi nhánh của tôi và master(hoặc bất kỳ chi nhánh nào bạn muốn chỉ định)


0

Điều này đã không làm việc cho tôi khi tôi đã làm một cái gì đó như develop > release-v1.0.0 > feature-foo , nó sẽ quay trở lại để phát triển, lưu ý rằng có một cuộc nổi loạn liên quan, không chắc đó có phải là vấn đề của tôi không ...

Sau đây đã cho băm xác nhận đúng cho tôi

git log --decorate \
  | grep 'commit' \
  | grep 'origin/' \
  | head -n 2 \
  | tail -n 1 \
  | awk '{ print $2 }' \
  | tr -d "\n"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.