簡體   English   中英

不允許分支合並到另一個分支

[英]Don't allow branch to merge to another branch

我有一個分支,我想允許它從另一個分支合並。 但是我不允許它合並到另一個分支(例如Dev,master)。

感謝幫助

您將發現執行此操作的簡便方法。 我可以大致告訴您您需要做什么; 但是您必須克服一些重要的障礙,而對於那些您一個人來說,因為我沒有浪費足夠的時間來充分發展我認為是個糟糕主意的想法。

唯一可能的解決方案是設置git hook。 您可以在原始存儲庫上放置一個預接收鈎子,這樣,如果有人嘗試執行包含您不喜歡的合並的推送,則可以拒絕該推送。 (面臨的挑戰是確定您不喜歡的合並;我會再說一遍。)

當然,當有人推動時,他們可能需要重做很多工作。 因此,您的開發人員知道他們不能推送違反您的規則的引用,因此他們可能希望安裝與預提交掛鈎相同的腳本以避免錯誤。 (假設他們不只是認為不值得在具有這種約束的項目上工作。)

棘手的部分是如何檢測要執行的合並類型。 您的腳本將必須分析任何新的合並,以查看第一和第二父級。 因此,您可能首先說,如果合並的第二個(或后續)父級等於master ,則拒絕推送。 所以如果你有

x -- x -- A <--(master)
 \
  x -- x -- B <--(dev)

有人不能簡單地說

git checkout dev
git merge master
git push

因為您的腳本看到新合並提交的第二個孩子是A ,即master 所以他們不能推

x ----- x ---- A <--(master)
 \              \
  x -- x -- B -- M <--(dev)

但是在那種情況下,您可能也不想讓他們推動

x ----- x ---- A -- C <--(master)
 \              \
  x -- x -- B -- M <--(dev)

如果這只鈎子看着master ,他們可以說

git checkout master
# stage some changes, or make the following commit with the allow-empty flag
git commit
git push
git checkout dev
git merge master^
git push

開發人員必須竭盡全力將master合並到dev,但是仍然可以做到。 而且由於您顯然希望將此規則作為一條規則,這意味着即使您沒有看到,開發人員也可以看到這些合並的價值,因此可以預期您將需要更嚴格地執行該規則。 因此,您的腳本實際上需要查找可以從 master 到達其第二(或后續)父級的任何合並。

因此,您可以使用git rev-list來構建無法合並的修訂列表,並檢查每個新的合並,以查找第二個(或后續)父級包含在該列表中。

但這可能會帶來一些意想不到的后果。 如果有的話

x -- x -- x -- M -- x <--(master)
 \    \       /
  \    x --- A <--(hotfix)
   \
    x -- x -- B <--(dev)

您可能應該允許將該修補程序合並到dev中,但是在此圖中,可以從master該修補程序。 (您可能需要先合並此修補程序才能進行dev然后再進行master ,但充其量是與人們可能做的事情相反的另一個任意約束。)

因此,也許當您使用rev-list構建禁止合並目標的列表時,您會為其指定first-parent參數。 這開始變得很難推理,因此目前尚不清楚它是否可以防彈,但我想它正在接近。

除了下一件事,如果有人使用reset來移動master ref,那么在推送時您不能說出他們正在合並的內容實際上是來自master分支怎么辦? 您要禁止所有強制執行操作嗎? (公平地說,應該謹慎使用推力。這一限制可能迫使開發人員考慮按常規使用它的工作流程,這是一個不好的主意。但是完全消除強制推力可能效果不佳。 )

哦,您的存儲庫越大( master的歷史越深),您的鈎子將變得越來越耗費資源(減慢push操作)。 我想你可以設置提交的最大數量的master來看待,這樣的假設沒有人會回去太遠尋找歷史的允許段從合並master 但這是腳本的另一種復雜性,可能會導致其變得過時。

所有這些的重點是,您可以花費大量的精力來控制您的開發人員,也可以設置人們一致認可的團隊實踐,因為他們是優秀的開發人員。

您可以通過將此答案調整為本地的pre-push掛鈎來接近解決方案(在這種情況下,所有開發人員都需要安裝掛鈎,因此您也可以考慮編寫一個腳本,使您可以將掛鈎保留在存儲庫中)使它更容易為你的開發者安裝), 或者您也可以重新配制溶液倒入pre-receive的起源掛鈎,更多的嚴格執行。

這個想法是使用標記來標識一個長期的“不良”提交(標記“不良”分支上的第一次提交),該提交永遠都不應被合並到您的干凈分支中,然后該鈎子查看git merge-base您要推送的ref和“壞”標簽之間的git merge-base ,如果它們一致,則拒絕推送。

這是我對該答案的改編,可用作pre-push鈎。 它包括一些邏輯,該邏輯允許包含錯誤提交的分支被推送,並且不打擾檢查推送標簽和其他非分支引用。

#!/bin/bash
#
# This prevents a push to the named remote if the push has any "forbidden"
# commits (indicated by a tag matching the forbidden_pat variable) as any
# ancestors. It prevents a known-bad branch from having its history
# intermingled with other branches.
#
# Adapted from http://stackoverflow.com/a/13384768

# which remote should we protect?
protected_remote="origin"

# which branch should allow forbidden commits?
skip_branch_regex='^test[1-3]$'

# what do our forbidden tags look like?
forbidden_pat="forbidden/*"

# only check if this is the remote we care about
if [ "$1" != "$protected_remote" ]; then
  exit 0
fi

# we might be trying to push multiple branches (e.g. push.default = matching).
# See http://git-scm.com/docs/githooks#_pre_push for the format
while read line
do
  words=($line)
  branch="${words[0]##refs/heads/}"
  ref="${words[1]}"

  # don't proceed if this is not a branch (IOW, if our substitution didn't
  # change anything; we only want to check pushing branch pointers, not tags or
  # other refs
  if [ "$branch" = "${words[0]}" ]; then
    continue
  fi

  # don't proceed if we're trying to push a branch that can receive the bad
  # commit
  if [[ "$branch" =~  $skip_branch_regex ]]; then
    continue
  fi

  # check each forbidden tag to see if it's an ancestor of the ref we're
  # trying to push; reject if it is.
  for forbidden in $(git tag -l "$forbidden_pat"); do
    if [ $(git merge-base "$forbidden" "$ref") = $(git rev-parse "$forbidden") ]; then
      echo "Push to $branch contains BAD commit $forbidden." >&2
      exit 1
    fi
  done
done
exit 0

在多開發人員環境中,這已經可以令人滿意地工作了。

綜上所述 ,我同意Mark Adelsberger的回答,即這不是要以編程方式解決的問題,而是應該以其他方式(培訓,自動化測試,簡化的分支工作流程等)解決的問題。

暫無
暫無

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

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