як ви натискаєте лише деякі з місцевих git-файлів?


160

Припустимо, у мене є 5 місцевих комітетів. Я хочу перенести лише 2 з них до централізованого репо (використовуючи робочий процес у стилі SVN). Як це зробити?

Це не спрацювало:

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

Це закінчується натисканням на всі 5 місцевих комітів.

Я припускаю, що я міг би скинути git, щоб фактично скасувати свої комітети, після чого - git stash, а потім git push - але у мене вже створені повідомлення про фіксацію та файли організовані, і я не хочу їх повторювати.

Моє відчуття, що якийсь прапор, переданий для натискання або скидання, спрацює.

Якщо це допомагає, ось моя конфігурація git

[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

Відповіді:


192

Якщо припустити, що ваші комісії перебувають у головній гілці, і ви хочете пересунути їх до віддаленої гілки:

$ git push origin master~3:master

Якщо ви використовували git-svn:

$ git svn dcommit master~3

У випадку з git-svn ви також можете використовувати HEAD ~ 3, оскільки він очікує фіксації. У випадку з прямим git, вам потрібно використовувати назву гілки, оскільки HEAD не оцінюється належним чином у refspec.

Ви також можете скористатися більш тривалим підходом до:

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

Якщо ви створюєте звичку до такого типу робочих потоків, вам слід розглянути можливість виконання своєї роботи в окремій галузі. Тоді ви можете зробити щось на кшталт:

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

Зауважте, що частина "master master: master", ймовірно, не потрібна для вашої установки.


14
Примітка: користуватися не потрібно master~3. Будь-яке посилання на бажану фіксацію "до" є однаково справедливою, наприклад, HEAD~3або HEAD~~~, або конкретна SHA, або тег, який мітить, що робить.
Каз

2
Хороший матеріал. Однак попередження: ці приклади підштовхують до початкового майстра. Якщо ви копіюєте та вставляєте це рішення, ви можете випадково оновити головну гілку. (Звичайно, ви завжди повинні бути обережними і двічі перевіряти свою команду, перш ніж видавати git push...)
nofinator

Здається, це підштовхує фіксацію, але не додає гілку віддалено.
Nateowami

@Nateowami для цього вам потрібно буде вказати щось інше, ніж masterвіддалену сторону респекту, як-отgit push origin tocommit:newbramch
Райан Грем

Я бачу. Назва філії вже існувала локально; Я думаю, це не сподобалось. У пульті ще не було назви гілки.
Nateowami

16

Те, що я роблю, - це робота в місцевій філії, яка називається "робота". Ця гілка містить всі тимчасові коміти (наприклад, обхідні шляхи чи параметри приватного збирання чи будь-що інше), які я не збираюся надсилати до сховища вище. Я працюю далеко на цій гілці, а потім , коли я хочу , щоб зробити переключаюсь на головній гілці, вишня підібрати відповідні коммітов , що я дійсно хочу , щоб зробити, а потім натисніть майстер.

Після втягування змін із верхнього потоку в мою головну гілку, я git checkout workі git rebase master. Це переписує всі мої локальні зміни, які мають бути наприкінці історії.

Я фактично використовую git svnцей робочий процес, тому моя операція "push" передбачає git svn dcommit. Я також використовую tigгарний перегляд текстового режиму перегляду сховища gui, щоб вишнево вибрати відповідні зобов’язання для оволодіння.


за допомогою git svn dcommit ви можете вказати комісію для dcommit до, тому потрібний ефект досить тривіальний для git-svn.
Райан Грехем

У цього підходу є недоліки (узагальнені тут stackoverflow.com/a/881014/1116674 ). Хорошою альтернативою є створення гілок для кожної функції, над якою ви працюєте, та workгілки. Потім ви з’єднуєте конкретні гілки в, masterщоб не втратити історію на них. Працюючи з work, ви об’єднуєте в нього всі свої гілки. Це більше накладних витрат, але, можливо, варто того в деяких випадках.
Хадон

16

За замовчуванням git-push відсуває всі гілки. Коли ви це зробите:

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

Ви переходите до відокремленої ГОЛОВИ (ви не знаходитесь ні на одній гілці), а потім виштовхуєте всі гілки, включаючи місцевого господаря (який все ще там, де він був), до віддаленого майстра.

Ручне рішення:

 git push origin HEAD:master

Якщо ви вважаєте, що поведінка за замовчуванням натискання всіх гілок плутається (і небезпечно!), Додайте це до своєї ~ / .gitconfig:

 [remote.origin]
    push = HEAD

Тоді висувається тільки гілка, на якій ти знаходишся. У вашому прикладі (відокремлена голова) ви отримали б це повідомлення про помилку, а не випадково натисканням неправильних зобов'язань:

 error: unable to push to unqualified destination: HEAD

10

Коротка відповідь:

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

Приклади:

git push fc47b2

git push HEAD~2

Довга відповідь:

Коміти пов'язані між собою як ланцюг з механізмом батьків / дитини. Таким чином, натискання на зобов’язання фактично також підштовхує всі батьківські зобов’язання до цього зобов’язання, що там, де віддалено не відомо. Це неявно робиться, коли ви виконуєте git pushпоточний фіксатор: усі попередні комітети також висуваються, оскільки ця команда еквівалентна git push HEAD.

Таким чином, питання може бути переписане на " Як підштовхнути певну комісію", і ця конкретна команда може бути, наприклад, HEAD ~ 2.

Якщо комісії, які ви хочете натиснути, не є послідовними, просто замовте їх git rebase -iпопередньо певним натисканням .


5

1) Використовуйте "git rebase", щоб змінити порядок виконання своїх зобов'язань.

git rebase -i

Ця команда відобразить щось подібне у вашому редакторі (я використовую 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) Впорядкуйте свої зобов’язання за своїм вибором за допомогою простої вирізаної пасти. Припустимо, новий порядок є

вибрати 9781434 коміс

виберіть c3d4961 комікс

виберіть 4791291 коміс

вибрати aa1cefc коміксD

виберіть команду a2bdfbd

Внесіть ці зміни у свій редактор і натисніть ctrl + O (writeOut)

Або ви також можете використовувати

git rebase -i HEAD~<commitNumber>

Ви можете перевірити нову послідовність за допомогою

git log

3) Тепер використовуйте

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

Якщо тільки одна гілка на віддаленому (походження) та одна в локальній (майстер), просто використовуйте

git push <commit SHA>
git push aa1cefc

Це підштовхне комісіюB і прихильністьD.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.