2009-03-02 39 views
123

Giả sử tôi có 5 cam kết cục bộ. Tôi muốn đẩy chỉ 2 trong số họ vào một repo tập trung (sử dụng một quy trình làm việc theo phong cách SVN). Làm thế nào để tôi làm điều này?làm thế nào để bạn chỉ đẩy một số cam kết git địa phương của bạn?

này đã không làm việc:

git checkout HEAD~3 #set head to three commits ago 
git push #attempt push from that head 

Đó kết thúc đẩy tất cả 5 địa phương cam kết.

Tôi giả sử tôi có thể thực hiện khôi phục git để thực sự hoàn tác các cam kết, tiếp theo là git stash và sau đó git push - nhưng tôi đã nhận được thư cam kết và tệp được sắp xếp và tôi không muốn làm lại chúng.

Cảm giác của tôi là một số cờ được chuyển đến đẩy hoặc đặt lại sẽ hoạt động.

Nếu nó giúp, đây là git của tôi cấu hình

[ramanujan:~/myrepo/.git]$cat config 
[core] 
     repositoryformatversion = 0 
     filemode = true 
     bare = false 
     logallrefupdates = true 
[remote "origin"] 
     url = ssh://server/git/myrepo.git 
     fetch = +refs/heads/*:refs/remotes/origin/* 
[branch "master"] 
     remote = origin 
     merge = refs/heads/master 

Trả lời

153

Giả cam kết của bạn đang ở trên chi nhánh tổng thể và bạn muốn đẩy họ đến chi nhánh chủ từ xa:

$ git push origin master~3:master 

Nếu bạn đang sử dụng git-svn:

$ git svn dcommit master~3 

Trong trường hợp git-svn, bạn cũng có thể sử dụng HEAD ~ 3, vì nó đang mong đợi một cam kết. Trong trường hợp git thẳng, bạn cần sử dụng tên chi nhánh vì HEAD không được đánh giá đúng trong refspec.

Bạn cũng có thể tham gia một cách tiếp cận dài:

$ git checkout -b tocommit HEAD~3 
$ git push origin tocommit:master 

Nếu bạn đang làm cho một thói quen của loại luồng công việc, bạn nên xem xét thực hiện công việc của bạn trong một chi nhánh riêng biệt. Sau đó, bạn có thể làm điều gì đó như:

$ git checkout master 
$ git merge working~3 
$ git push origin master:master 

Lưu ý rằng phần "gốc chính: chủ" có thể là tùy chọn cho thiết lập của bạn.

+10

Lưu ý: bạn không phải sử dụng 'master ~ 3'. Bất kỳ tham chiếu nào tới cam kết "lên tới" mong muốn đều có giá trị như nhau, chẳng hạn như 'HEAD ~ 3' hoặc' HEAD ~~~ 'hoặc SHA cụ thể hoặc thẻ gắn nhãn cam kết đó. – Kaz

+1

Nội dung hay. Một cảnh báo mặc dù: những ví dụ này đẩy đến master gốc. Nếu bạn đang sao chép và dán giải pháp này, bạn có thể vô tình cập nhật nhánh chính. (Tất nhiên, bạn nên luôn cẩn thận và kiểm tra lại lệnh của mình trước khi phát hành 'git push' ...) – nofinator

+0

Dường như điều này đẩy cam kết, nhưng không thêm nhánh từ xa. – Nateowami

15

Những gì tôi làm việc trên một chi nhánh địa phương gọi là "công việc" này. Nhánh này chứa tất cả các cam kết tạm thời (như cách giải quyết hoặc các tùy chọn xây dựng riêng hoặc bất kỳ thứ gì) mà tôi không có ý định đẩy tới kho lưu trữ ngược dòng. Tôi làm việc trên nhánh đó, sau đó khi tôi muốn cam kết tôi chuyển sang nhánh chính, anh đào-chọn các cam kết thích hợp mà tôi làm muốn cam kết, sau đó nhấn chính.

Sau khi kéo các thay đổi từ thượng nguồn vào nhánh chính, tôi git checkout workgit rebase master. Điều đó ghi đè tất cả các thay đổi cục bộ của tôi ở cuối lịch sử.

Tôi thực sự đang sử dụng git svn với quy trình làm việc này, vì vậy hoạt động "đẩy" của tôi liên quan đến git svn dcommit. Tôi cũng sử dụng tig là chế độ xem kho gui chế độ văn bản đẹp, để chọn lựa các cam kết phù hợp để làm chủ.

+0

với git svn dcommit, bạn có thể chỉ định một cam kết để dcommit lên đến, do đó, hiệu quả mong muốn là khá tầm thường với git-svn. –

+0

Có những bất lợi cho cách tiếp cận này (tóm tắt ở đây http://stackoverflow.com/a/881014/1116674). Một lựa chọn tốt là tạo các nhánh cho mọi tính năng bạn đang làm việc và một nhánh 'work'. Sau đó, bạn hợp nhất các nhánh cụ thể thành 'master' để bạn không bị mất lịch sử trên chúng. Khi làm việc với 'work', bạn hợp nhất tất cả các nhánh của bạn vào nó. Đó là chi phí cao hơn, nhưng có thể là giá trị nó trong một số trường hợp. – Hudon

11

Theo mặc định, git-push đẩy tất cả các nhánh. Khi bạn làm điều này:

git checkout HEAD~3 #set head to three commits ago 
git push #attempt push from that head 

Bạn di chuyển đến một TRỤ tách ra (bạn không phải trên bất kỳ chi nhánh) và sau đó bạn đẩy tất cả các chi nhánh, trong đó có chủ địa phương (trong đó vẫn là nơi nó được) để điều khiển từ xa bậc thầy.

Giải pháp thủ công là: (! Và nguy hiểm)

git push origin HEAD:master 

Nếu bạn tìm thấy những hành vi mặc định đẩy các ngành khó hiểu, thêm này vào ~/.gitconfig:

[remote.origin] 
    push = HEAD 

Sau đó, chỉ nhánh bạn đang ở được đẩy. Trong ví dụ của bạn (một đầu tách ra), bạn sẽ có được thông báo lỗi này, chứ không phải là vô tình đẩy các cam kết sai:

error: unable to push to unqualified destination: HEAD 
4

1) Sử dụng "git rebase" để sắp xếp lại các cam kết của bạn, nếu bạn muốn.

git rebase -i 

Lệnh này sẽ hiển thị một cái gì đó như thế này trong trình soạn thảo của bạn (Tôi đang sử dụng vim)

pick 4791291 commitA 
pick a2bdfbd commitB 
pick c3d4961 commitC 
pick aa1cefc commitD 
pick 9781434 commitE 

# Rebase .............. 
# 
# Commands: 
# p, pick = use commit 
# r, reword = use commit, but edit the commit message 
# e, edit = use commit, but stop for amending 
# s, squash = use commit, but meld into previous commit 
# f, fixup = like "squash", but discard this commit's log message 
# x, exec = run command (the rest of the line) using shell 
# 
# These lines can be re-ordered; they are executed from top to bottom. 
# 
# If you remove a line here THAT COMMIT WILL BE LOST. 
# 
# However, if you remove everything, the rebase will be aborted. 
# 
# Note that empty commits are commented out 




^G Get Help   ^O WriteOut   ^R Read File  ^Y Prev Page    ^K Cut Text   ^C Cur Pos 
^X Exit    ^J Justify   ^W Where Is   ^V Next Page   ^U UnCut Text  ^T To Spell 

2) Sắp xếp lại bạn cam kết của bạn theo sự lựa chọn của bạn bằng cách dán cắt đơn giản. Giả sử thứ tự mới là

đón 9.781.434 commitE

pick c3d4961 commitC

đón 4.791.291 commitA

pick aa1cefc commitD

pick a2bdfbd commitB

Thực hiện các thay đổi trong trình soạn thảo của bạn và nhấn ctrl + O (writeOut)

Hoặc bạn cũng có thể sử dụng

git rebase -i HEAD~<commitNumber> 

Bạn có thể kiểm tra các chuỗi mới với

git log 

3) Bây giờ sử dụng

git push <remoteName> <commit SHA>:<remoteBranchName> 

Nếu chỉ có một chi nhánh tại từ xa (nguồn gốc) và một tại địa phương (chính), chỉ cần sử dụng

git push <commit SHA> 
git push aa1cefc 

Điều này sẽ đẩy commitB và commitD.

3

Câu trả lời ngắn:

git push <latest commit SHA1 until you want commits to be pushed>

Ví dụ:

git push fc47b2

git push HEAD~2

Long trả lời:

cam được liên kết với nhau như một chuỗi với cơ chế cha/con.Do đó, đẩy cam kết thực sự cũng đẩy tất cả các phụ huynh cam kết vào cam kết này mà ở đó không được biết đến từ xa. Điều này hoàn toàn được thực hiện khi bạn git push cam kết hiện tại: tất cả các cam kết trước đó cũng được đẩy vì lệnh này tương đương với git push HEAD.

Vì vậy, câu hỏi có thể được viết lại thành Cách ấn cam kết cụ thể và cam kết cụ thể này có thể là HEAD ~ 2 chẳng hạn.

Nếu các cam kết bạn muốn đẩy không liên tục, chỉ cần đặt lại chúng với một git rebase -i trước khi đẩy cụ thể.

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