2012-02-01 19 views
9

Tôi có một kho lưu trữ đơn giản với lịch sử tuyến tính của cam kết, như:Làm cách nào để áp dụng lại các cam kết ở trên cùng của chi nhánh không liên quan?

[A] -> [B] -> [C] -> [D] -> [E] ... 

tôi về cơ bản cần phải loại bỏ cam kết A và B vì vậy tôi nghĩ rằng tôi muốn tạo ra một kho lưu trữ mới và muốn đạt được cái gì đó như:

[X] -> [C] -> [D] -> [E] ... 

Vì vậy, tôi đã tạo kho lưu trữ mới, cam kết X đã tạo thủ công, lưu trữ thông tin liên quan từ A và B và bây giờ cần lệnh sẽ mang cam kết C, D, E, v.v ... nó trên đầu trang của cam kết mới của tôi X.

Làm thế nào để làm điều đó?

Edit: Hai vấn đề tôi có với các phương pháp cherry-pick đề xuất là:

  1. Chuyển cam mất ngày của họ. Có cách nào để bảo tồn ngày cam kết không?
  2. Khi tôi tìm nạp chính từ kho lưu trữ ban đầu (và chủ từ xa đó không có bất kỳ cam kết chung nào với kho lưu trữ mới), tôi gặp sự cố khi xóa các cam kết đã tìm nạp đó. Khi tôi làm git branch -D myoriginalrepo/master, nó nói rằng không có nhánh nào tồn tại trong khi tôi có thể thấy rõ ràng những cam kết đó trong công cụ GUI của tôi.
+0

Tôi nghĩ bạn nên xem git cherry-pick. –

+0

Bạn đã bao giờ tìm ra cách giữ ngày tháng thay đổi? – thinsoldier

Trả lời

15

Không chắc lý do tại sao bạn cần ngày cam kết giữ nguyên nhưng ở đây đi:

git rebase B E --onto X --committer-date-is-author-date 

Nếu B..E không nằm trong kho lưu trữ giống như X (vì chúng có thể là if you create your fresh start in-place), bạn sẽ cần phải lấy họ đầu tiên:

git fetch <path_to_old_repos> 

Tất nhiên, B, EX đây có nghĩa là họ cam-id nếu bạn chưa thực sự gắn thẻ/nhánh họ.

Bạn cũng có thể làm điều gì đó tương tự (mặc dù ngày cam kết sẽ không được giữ) bởi rebasing từ A trong kho lưu trữ ban đầu của bạn và đè bẹp B vào nó:

git rebase -i `A` 

# change "pick b" to "squash b" 

Bạn sẽ nhận được một cơ hội để thay đổi cam kết tin nhắn tại thời điểm đó bạn có thể làm cho nó X của.

+0

Điều này nghe có vẻ như cách tiếp cận tốt nhất cho đến nay, tuy nhiên, tôi gặp sự cố khi làm việc với các commit được tìm nạp bằng cách sử dụng 'git fetch'. Làm thế nào để tôi tham khảo chúng? Họ không thuộc bất kỳ chi nhánh nào, đúng không? – Borek

+2

'git fetch' sẽ tạo cho bạn một nhánh thuận tiện gọi là' FETCH_HEAD' sẽ trỏ đến bất kỳ 'HEAD' nào (nghĩa là bất kỳ điều gì đã được kiểm tra) trong kho lưu trữ cũ của bạn. Hơn nữa, các commit-id sẽ giống hệt nhau trên các kho lưu trữ, do đó bạn có thể chỉ cần truy cập 'git log ' chẳng hạn. Bạn cũng có thể chọn tạo một nhánh tương ứng trong khi tìm nạp: 'git fetch their_branch: my_branch'. – antak

3

Bạn có thể sử dụng git cherry-pick. Trong trường hợp của bạn:

git cherry-pick C D E 

trong khi X là đầu bạn nên làm.

+0

Cảm ơn, tôi nghĩ rằng rebase sẽ là bạn của tôi nhưng lựa chọn anh đào là lệnh để sử dụng. Tôi hy vọng tôi có thể xác định các cam kết như "C .." như tôi có hàng trăm người trong số họ trong repo gốc. – Borek

+0

Nếu bạn có rất nhiều, có một số tùy chọn lựa chọn anh đào sẽ cho phép bạn nhóm chúng lại. Kiểm tra tài liệu. Rebase cũng sẽ hoạt động - nếu bạn sử dụng nó trên kho gốc để thay thế A & B bằng X, bạn sẽ kết thúc với cùng một kết quả mà bạn đang tìm kiếm. –

+1

Chọn Cherry dường như mất thông tin ngày cam kết (nó có thể tạo ra một cam kết mới), liệu vấn đề có giống nhau với việc rebase không? Điều đó sẽ khá tệ, tôi cần phải duy trì ngày cam kết. – Borek

1

Bạn nói bạn đã tạo "một kho lưu trữ mới". Có thể bạn không muốn làm điều đó. Nếu vì lý do nào đó, các cam kết A và B hoàn toàn chấm dứt tồn tại (ví dụ vì lý do pháp lý hoặc vì bạn vô tình cam kết số thẻ tín dụng và công thức bí mật của bạn cho haggis) trong kho lưu trữ của bạn, bạn sẽ cần phải đọc về cách xóa vĩnh viễn một cam kết . Nhưng trước tiên hãy sửa phần còn lại của cây.

Hãy thử một cái gì đó giống như

git checkout -b freshstart A 
# modify the state of the system until it reflects your desired new beginning X 
git commit --amend 
git cherry-pick C D E 

Bây giờ bạn có một chi nhánh tên là freshstart trong đó có đầu X mới của bạn và cam kết C, D và E giả sử họ kết hợp độc đáo vào X.

+0

Đúng vậy, A và B phải được loại bỏ hoàn toàn khỏi lịch sử để tạo ra một repo mới có vẻ như là một cách tốt để bắt đầu. Tôi tạo ra một trạng thái X, lấy nhánh gốc từ xa-repo/master và bây giờ tôi có thể chọn các cam kết từ nó vào nhánh chính. Hai vấn đề tôi có: 1) Cherry chọn cam kết mất ngày 2) Tôi không thể tham khảo nhánh gốc/repo/master (vì nó không có bất kỳ cha mẹ chung nào với master địa phương và đứng bên cạnh 'master' của tôi). Tôi không thể xóa nhánh tạm thời mà tôi đã hái từ anh ấy. – Borek

+1

Bạn không cần một repo mới để xóa hoàn toàn các cam kết. Bạn có thể sử dụng rebase, ví dụ, để loại bỏ các cam kết. Điều duy nhất là nếu bạn có lý do pháp lý hoặc một cái gì đó để loại bỏ cam kết, bạn phải đảm bảo rằng các đối tượng trở thành rác khi bạn loại bỏ các cam kết được làm sạch để họ vẫn không có sẵn cho những người biết những gì họ đang làm. Và tất nhiên bạn phải đi đến mọi bản sao của repo ở khắp mọi nơi và làm điều tương tự hoặc bạn có thể không sống theo nghĩa vụ pháp lý. – bames53

+0

A và X không có bất kỳ commit nào trước đây, có thể tạo một chi nhánh không có cha/mẹ trong repo gốc của tôi không? – Borek

Các vấn đề liên quan