Làm cách nào để tôi 'ghi đè', thay vì 'hợp nhất', một nhánh trên một nhánh khác trong Git?


257

Tôi có hai chi nhánh, emailstaging. staginglà cái mới nhất và tôi không còn cần những thay đổi cũ trong emailchi nhánh, nhưng tôi không muốn xóa chúng.

Vì vậy, tôi chỉ muốn đổ tất cả nội dung stagingvào emailđể cả hai cùng trỏ đến cùng một cam kết. Điều đó có thể không?


Câu trả lời:


196

Bạn có thể sử dụng chiến lược hợp nhất 'của chúng ta':

$ git checkout staging
$ git merge -s ours email # Merge branches, but use our branch head

26
Tôi đã thử điều này, và nó dường như ngược với tôi? Điều này không biến nội dung của email thành dàn dựng và không phải là cách khác?
Tối đa

27
@Max Tôi cũng có sự nhầm lẫn tương tự và nó gây cho tôi rất nhiều rắc rối. Bạn cần thực hiện lệnh này từ nhánh mới hơn (dàn dựng), và sau đó thực hiện hợp nhất / PR bình thường cho nhánh cũ của bạn (email).
MrGlass

7
Tại sao ;ở cuối mỗi lệnh? Tôi đã làm mà không có ;và nó dường như đang làm việc. Ngoài ra câu trả lời này là không đầy đủ, bước thứ ba là kiểm tra chi nhánh cũ (email) và sau đó hợp nhất với dàn dựng lại.
Rosdi Kasim

4
git rebase -s theirs <oldbranc> <newbranch> hoạt động tốt (cho dù bạn ở chi nhánh nào). Lưu ý rằng trong rebase, 'của họ' thực sự là người mới vì 'chúng ta' là người đứng đầu chúng ta hiện đang áp dụng các cam kết.
Rolf

4
@Rolf: nhưng rebase sẽ thoát khỏi thông tin hợp nhất và làm phẳng lịch sử. Không nhất thiết là những gì bạn đang sau. Cũng không phải là một ý tưởng tốt, nếu bạn đang làm việc với lịch sử đã được xuất bản.
knittl

99

Nếu bạn chỉ muốn hai nhánh 'email' và 'staging' giống nhau, bạn có thể gắn thẻ nhánh 'email', sau đó đặt lại nhánh 'email' thành nhánh 'staging':

$ git checkout email
$ git tag old-email-branch
$ git reset --hard staging

Bạn cũng có thể khởi động lại nhánh 'dàn dựng' trên nhánh 'email'. Nhưng kết quả sẽ chứa sự sửa đổi của hai nhánh.


1
bạn có thể có nghĩa là git checkout, git checkkhông tồn tại theo hiểu biết của tôi
knittl

4
Bạn nói đúng, tôi đã quá quen với việc hoàn thành tab git mà tôi luôn viết "git check <TAB>" để viết "git checkout"! Đã sửa.
Sylvain Defresne

17
git reset phá vỡ repo của những người khác đã nhân bản repo của bạn
Geoffrey De Smet

Tôi tin rằng đây là câu trả lời đúng. emailĐầu của chi nhánh chỉ nên trỏ đến cùng một đầu stagingvà cả hai sẽ có cùng một cam kết, cùng một lịch sử.
cicerocamargo

76

Tôi đã thấy một số câu trả lời và đó là quy trình duy nhất cho phép tôi khắc phục điều đó mà không có bất kỳ xung đột nào.

Nếu bạn muốn tất cả các thay đổi từ Branch_new trong Branch_old, thì:

git checkout branch_new
git merge -s ours branch_old
git checkout branch_old
git merge branch_new

một khi áp dụng bốn lệnh đó, bạn có thể đẩy Branch_old mà không gặp vấn đề gì


5
Câu trả lời của bạn thực sự phù hợp với vấn đề của tôi nhất vì tôi không muốn thiết lập lại CHÍNH, chỉ nêu một ưu tiên cho các tệp mới hơn trong nhánh mới hơn khi hợp nhất mọi thứ vào tệp cũ hơn và hoạt động mà không gặp sự cố! +1
bếp lò

Tôi đã đẩy Branch_new của mình đến điều khiển từ xa sau khi "chúng ta hợp nhất" và phương pháp này hiệu quả với tôi. Có cần thiết cho tôi để đẩy? Hoặc nó sẽ làm việc mà không có? (Không chắc chắn nếu nó sẽ sử dụng chi nhánh địa phương hoặc từ xa). Cảm ơn!
aspergillusOryzae

Tại sao bạn không thể làm những điều dưới đây? git checkout branch_old git merge -s họ Clue branch_new lấy từ stackoverflow.com/questions/14275856/...
Ripu Daman

Nó nói, không thể tìm thấy chiến lược hợp nhất "của họ".
arango_86

Hoạt động hoàn hảo với tôi, có lợi thế là không thiết lập lại bất cứ điều gì
Romain

68

Các câu trả lời khác cho tôi manh mối đúng, nhưng chúng không hoàn toàn giúp được.

Đây là những gì làm việc cho tôi:

$ git checkout email
$ git tag old-email-branch # This is optional
$ git reset --hard staging
$
$ # Using a custom commit message for the merge below
$ git merge -m 'Merge -s our where _ours_ is the branch staging' -s ours origin/email
$ git push origin email

Nếu không có bước thứ tư hợp nhất với chiến lược của chúng tôi, cú hích được coi là một bản cập nhật không chuyển tiếp nhanh và sẽ bị từ chối (bởi GitHub).


Điều đó làm cho thông điệp cam kết hợp nhất sai, nhưng vâng, nó hoạt động rất tốt.
cdunn2001

cdunn2001, tôi tò mò. Thông điệp cam kết hợp nhất mà bạn đang mong đợi là gì và làm thế nào mà nó bị rối với điều này?
Shyam Habarakada

Nó nói "Hợp nhất chi nhánh theo dõi từ xa 'origin / email' vào email". Nó không đề cập đến việc dàn dựng. Không có vấn đề lớn mặc dù. Chỉ cần sửa đổi cam kết, hoặc sử dụng merge -m 'This is not my beautiful house.' -s ours origin/email.
cdunn2001

@ShyamHabarakada, tôi làm như bạn nói, và tôi gặp vấn đề về cập nhật không nhanh. bởi vì không có gì xảy ra khi tôi làm bước thứ 4
kommradHomer

Bước 4 yêu cầu bạn sử dụng nguồn gốc / email, nó không hoạt động chỉ với email cục bộ.
Travis Reeder

45

Nếu bạn giống như tôi và bạn không muốn đối phó với việc hợp nhất, bạn có thể thực hiện các bước trên, ngoại trừ sử dụng vũ lực thay vì hợp nhất, vì nó sẽ tạo ra một dấu vết giấy nhật ký gây mất tập trung:

git checkout email
git reset --hard staging
git push origin email --force

Lưu ý: Điều này chỉ khi bạn THỰC SỰ không bao giờ muốn nhìn thấy những thứ trong email nữa.


1
git đẩy email gốc - Force không hoạt động với tôi khi Step2 rời các nhánh. Vì vậy, sau Bước 2, đây là những gì tôi đã làm: git reset origin / email và sau đó git đẩy
user3505394

2
Đây chính xác là những gì đã được hỏi trong câu hỏi - "làm thế nào để ghi đè thay vì hợp nhất". Nên chấp nhận trả lời.
tham gia

17

Tôi muốn hợp nhất hai nhánh để tất cả các nội dung old_branchđược cập nhật với nội dung từnew_branch

Đối với tôi điều này làm việc như một cơ duyên:

$ git checkout new_branch
$ git merge -m 'merge message' -s ours origin/old_branch
$ git checkout old_branch
$ git merge new_branch
$ git push origin old_branch

10

Làm thế nào về:

git branch -D email
git checkout staging
git checkout -b email
git push origin email --force-with-lease

@emptywalls vì nó thực hiện một cú đẩy mạnh mẽ mà không cảnh báo người dùng rằng nó có thể bị máy chủ từ chối, và cũng không giải thích được tại sao cần thiết. Điều đó nói rằng, đó là một lựa chọn khả thi cho một dự án một nhà phát triển
David Costa

@DavidCosta tại sao điều này sẽ bị máy chủ từ chối? đây là một nhánh xóa email đơn giản và sao chép dàn dựng vào email '... Vì vậy, tôi chỉ muốn chuyển tất cả nội dung của' dàn dựng 'vào' email 'để cả hai cùng chỉ ra một cam kết' - đó chính xác là những gì đang xảy ra đây.
Arek S

@ArekS có thể bị từ chối bởi hook phía máy chủ nếu nhánh được đặt là "được bảo vệ", ví dụ như trong GitLab. Vấn đề là nếu người khác lấy chi nhánh của anh ta từ email trước thao tác này và sau đó cố gắng đẩy, thì các tham chiếu không khớp nữa (vì một số cam kết đơn giản biến mất)
David Costa

1
Tôi đã chỉnh sửa bản gốc từ - Force thành - Force-with-cho thuê, đó là mánh khóe theo cách không phá hủy.
frandroid

1
Đây là cách tốt nhất nếu bạn chỉ muốn thổi bay một nhánh và khởi động nó khỏi nhánh nguồn.
Shane

6

Các câu trả lời khác nhìn không đầy đủ.
Tôi đã thử đầy đủ dưới đây, và nó hoạt động tốt.

LƯU Ý:
1. Tạo một bản sao của kho lưu trữ của bạn trước khi bạn thử bên dưới, để ở bên an toàn.

Chi tiết:
1. Tất cả sự phát triển xảy ra trong nhánh dev
2. Chi nhánh qa chỉ là cùng một bản sao của dev
3. Thỉnh thoảng, mã dev cần được di chuyển / ghi đè lên nhánh qa

vì vậy chúng ta cần ghi đè lên nhánh qa, từ nhánh dev

Phần 1:
Với các lệnh bên dưới, qa cũ đã được cập nhật lên dev mới hơn:

git checkout dev
git merge -s ours qa
git checkout qa
git merge dev
git push

Nhận xét tự động cho lần đẩy cuối cùng bên dưới:

// Output:
//  *<MYNAME> Merge branch 'qa' into dev,*  

Nhận xét này có vẻ ngược lại, bởi vì trình tự trên cũng có vẻ đảo ngược

Phần 2:

Dưới đây là bất ngờ, các cam kết địa phương mới trong dev, những thứ không cần thiết
vì vậy, chúng ta cần phải vứt bỏ và làm cho dev không bị ảnh hưởng.

git checkout dev

// Output:
//  Switched to branch 'dev'  
//  Your branch is ahead of 'origin/dev' by 15 commits.  
//  (use "git push" to publish your local commits)


git reset --hard origin/dev  

//  Now we threw away the unexpected commits

Phần 3:
Xác minh mọi thứ như mong đợi:

git status  

// Output:
//  *On branch dev  
//  Your branch is up-to-date with 'origin/dev'.  
//  nothing to commit, working tree clean*  

Đó là tất cả.
1. qa cũ hiện bị ghi đè bởi mã nhánh dev mới
2. local is clean (nguồn gốc từ xa / dev không bị ảnh hưởng)


6

Cách dễ nhất để làm điều đó:

//the branch you want to overwrite
git checkout email 

//reset to the new branch
git reset --hard origin/staging

// push to remote
git push -f

Bây giờ chi nhánh email và dàn dựng là như nhau.


2
Cảnh báo: Điều này xóa tất cả các cam kết trên emailnhánh. Nó giống như xóa emailchi nhánh và tạo lại nó ở đầu stagingchi nhánh.
Cameron Hudson

2
git checkout email
git merge -m "Making email same as staging disregarding any conflicts from email in the process" -s recursive -X theirs staging

1
Câu trả lời này sẽ rõ ràng hơn với tôi nếu bình luận được tách biệt với bình luận hợp nhất trong lệnh. Giải thích ngắn gọn những gì -X làm và cách nó ảnh hưởng đến sự hợp nhất này. Cảm ơn mặc dù. Làm cho tôi tìm nó :)
noelicus

@noelicus cảm ơn vì nhận xét và bạn nói đúng. Tôi có thể chỉnh sửa câu trả lời trong tương lai.
Willa

0

Cái này không làm thay đổi nhánh mới hơn ban đầu và cho bạn cơ hội thực hiện các sửa đổi thêm trước khi cam kết cuối cùng.

git checkout new -b tmp
git merge -s ours old -m 'irrelevant'
git checkout old
git merge --squash tmp
git branch -D tmp
#do any other stuff you want
git add -A; git commit -m 'foo' #commit (or however you like)
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.