Как вы нажимаете только некоторые из ваших локальных 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 - но у меня уже есть записанные сообщения и файлы, t хотят их переделать.
Я чувствую, что какой-то флаг прошел, чтобы нажать или reset будет работать.
Если это помогает, вот мой git config
[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
Ответы
Ответ 1
Предполагая, что ваши коммиты находятся на главной ветке, и вы хотите нажать их на удаленную ведущую ветвь:
$ 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", вероятно, является необязательной для вашей установки.
Ответ 2
То, что я делаю, это работа над локальным филиалом под названием "работа". Эта ветка содержит все временные коммиты (например, обходные пути или частные варианты сборки или что-то еще), которые я не намерен использовать для восходящего репозитория. Я работаю на этой ветке, а затем, когда я хочу совершить переход на главную ветку, вишни выберите соответствующие коммиты, которые я хочу совершить, затем нажмите мастер.
После того, как вы переместили изменения в верхнюю часть моей основной ветки, я git checkout work
и git rebase master
. Это переписывает все мои локальные изменения в конце истории.
Я использую git svn
с этим рабочим процессом, поэтому моя операция "push" включает git svn dcommit
. Я также использую tig
, который представляет собой просмотрщик репозитория с хорошим текстовым режимом, чтобы вишневый выбор соответствующих коммитов для мастеринга.
Ответ 3
По умолчанию 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
Ответ 4
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 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 commitE
выберите 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.
Ответ 5
Короткий ответ:
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
перед конкретным нажатием.