Как вы продвигаете только некоторые из ваших локальных коммитов git?
Предположим, у меня есть 5 локальных коммитов. Я хочу подтолкнуть только 2 из них к централизованному репо (используя рабочий процесс в стиле SVN). Как мне это сделать?
Это не сработало:
git checkout HEAD~3 #set head to three commits ago
git push #attempt push from that head
Это в конечном итоге подталкивает все 5 локальных коммитов.
Я полагаю, что мог бы сделать git reset, чтобы фактически отменить мои коммиты, затем git stash, а затем git push - но у меня уже есть записанные сообщения коммитов и организованные файлы, и я не хочу их переделывать.
Я чувствую, что какой-то флаг, переданный для нажатия или сброса, будет работать.
Если это поможет, вот мой конфиг
[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
5 ответов
Предполагая, что ваши коммиты находятся в главной ветви, и вы хотите перенести их в удаленную главную ветку:
$ 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
Обратите внимание, что часть "origin master:master", вероятно, не является обязательной для вашей установки.
Короткий ответ:
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
перед конкретным толчком.
Что я делаю, так это работаю в местном отделении под названием "работа". Эта ветвь содержит все временные коммиты (такие как обходные пути или опции частной сборки или что-то еще), которые я не собираюсь выдвигать в обратный репозиторий. Я работаю над этой веткой, затем, когда я хочу зафиксировать, я переключаюсь на основную ветку, выбираю нужные коммиты, которые я хочу зафиксировать, затем нажимаю мастер.
Вытащив изменения из апстрима в мою основную ветку, я git checkout work
а также git rebase master
, Это переписывает все мои локальные изменения, чтобы быть в конце истории.
Я на самом деле использую git svn
с этим рабочим процессом, так что моя операция "подтолкнуть" включает в себя git svn dcommit
, Я также использую tig
который является хорошим средством просмотра репозитория графического интерфейса в текстовом режиме, для выбора соответствующих коммитов мастеру.
По умолчанию git-push помещает все ветви. Когда вы делаете это:
git checkout HEAD~3 #set head to three commits ago
git push #attempt push from that head
Вы переходите к отдельному HEAD (вы не находитесь ни в одной ветви), а затем перемещаете все ветви, включая локальный мастер (который все еще там, где он был), к удаленному мастеру.
Ручное решение:
git push origin HEAD:master
Если вы обнаружите, что поведение по умолчанию для всех веток сбивает с толку (и опасно!), Добавьте это в ваш ~/.gitconfig:
[remote.origin]
push = HEAD
Тогда толкается только та ветка, на которой вы находитесь. В вашем примере (отдельная голова) вы бы получили это сообщение об ошибке, а не случайно нажали неправильные коммиты:
error: unable to push to unqualified destination: HEAD
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 commitC
выбрать 4791291 commitA
выберите aa1cefc commitD
выберите a2bdfbd commitB
Сделайте эти изменения в вашем редакторе и нажмите Ctrl+ O (writeOut)
Или вы также можете использовать
git rebase -i HEAD~<commitNumber>
Вы можете проверить новую последовательность с
git log
3) Теперь используйте
git push <remoteName> <commit SHA>:<remoteBranchName>
Если только одна ветка на удаленной (источник) и одна на локальной (мастер), просто используйте
git push <commit SHA>
git push aa1cefc
Это подтолкнет commitB и commitD.