как вы толкаете только некоторые из ваших локальных коммитов git?

<p>предположим, у меня есть 5 локальных коммитов. я хочу перенести только 2 из них в централизованное хранилище (используя рабочий процесс в стиле svn). как мне это сделать?</p><p>это не сработало:</p><pre><code>git checkout head~3 #set head to three commits ago git push #attempt push from that head </code></pre><p>это заканчивает тем, что выдвигало все 5 локальных коммитов.</p><p>я полагаю, что я мог бы сделать git reset, чтобы фактически отменить мои коммиты, затем git stash, а затем git push - но у меня уже есть записанные сообщения коммитов и организованные файлы, и я не хочу повторять их.</p><p>я чувствую, что какой-то флаг, переданный в push или сброс, будет работать.</p><p>если это поможет, вот мой конфиг</p><pre><code>[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 

предполагая, что ваши коммиты находятся в главной ветви, и вы хотите перенести их в удаленную главную ветку:$ git push origin master~3:master </code></pre><p>если вы использовали git-svn:</p><pre><code>$ 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 </code></pre><p>обратите внимание, что часть "origin master: master", вероятно, не является обязательной для вашей настройки.</p>

<p>что я делаю, так это работаю в местном отделении под названием "работа". эта ветвь содержит все временные коммиты (такие как временные решения или опции частной сборки или что-то еще), которые я не собираюсь отправлять в обратный репозиторий. я работаю над этой веткой, затем, когда я хочу сделать коммит, я переключаюсь на основную ветвь и выбираю нужные коммиты, которые я <em> </em> хочу зафиксировать , затем толкни мастер.</p><p>после извлечения изменений из апстрима в мою основную ветку я <code>git checkout work</code> и <code>git rebase master</code>. это переписывает все мои локальные изменения, чтобы быть в конце истории.</p><p>я на самом деле использую <code>git svn</code> с этим рабочим процессом, поэтому моя операция "push" включает <code>git svn dcommit</code>. я также использую <a href="http://jonas.nitro.dk/tig/"><code>tig</code></a> , которая является средством просмотра репозитория графического интерфейса в текстовом режиме nice, для выбора подходящих коммитов.</p>

<p>по умолчанию git-push выдвигает все ветви. когда вы делаете это:</p><pre><code> git checkout head~3 #set head to three commits ago git push #attempt push from that head </code></pre><p>вы переходите к отдельному head (вы не находитесь ни в одной ветви), а затем проталкиваете все ветви, включая локальный мастер (который все еще там, где он был), к удаленному мастеру.</p><p>ручное решение:</p><pre><code> git push origin head:master </code></pre><p>если вы обнаружите, что поведение по умолчанию для всех веток сбивает с толку (и опасно!), добавьте это в ваш ~/.gitconfig:</p><pre><code> [remote.origin] push = head </code></pre><p>тогда толкается только та ветка, на которой вы находитесь. в вашем примере (отдельная голова) вы бы получили это сообщение об ошибке, а не случайно нажали неправильные коммиты:</p><pre><code> error: unable to push to unqualified destination: head </code></pre>

<h1>короткий ответ:</h1><p><code>git push <latest commit sha1 until you want commits to be pushed></code></p><p>примеры:</p><p><code>git push fc47b2</code></p><p><code>git push head~2</code></p><h1>длинный ответ:</h1><p>коммиты связаны друг с другом в виде цепочки с родительским/дочерним механизмом. таким образом, <em>отправка коммита</em> на самом деле также толкает <em>все родительские коммиты</em> к этому коммиту, который неизвестен удаленному. это неявно делается, когда вы <code>git push</code> текущий коммит: все предыдущие коммиты также передаются, потому что эта команда эквивалентна <code>git push head</code>.</p><p>таким образом, вопрос может быть переписан в <em>как протолкнуть конкретный коммит</em> и этот конкретный коммит может быть, например, head ~ 2.</p><p>если коммиты, которые вы хотите нажать, не являются последовательными, просто измените их порядок с помощью <code>git rebase -i</code> перед <em>конкретным push</em>.</p>

<p>1) используйте "git rebase", чтобы изменить порядок ваших коммитов, если хотите.</p><pre><code>git rebase -i </code></pre><p>эта команда отобразит что-то вроде этого в вашем редакторе (я использую vim)</p><pre><code>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 </code></pre><p>2) упорядочить ваши коммиты по вашему выбору с помощью простой резки пасты. предположим, новый заказ</p><p>выбрать 9781434 коммит</p><p>выбрать c3d4961 commitc</p><p>выбрать 4791291 commita</p><p>выберите aa1cefc commitd</p><p>выбрать a2bdfbd commitb</p><p>сделайте эти изменения в вашем редакторе и нажмите ctrl + o (writeout)</p><p>или вы также можете использовать</p><pre><code>git rebase -i head~<commitnumber> </code></pre><p>вы можете проверить новую последовательность с</p><pre><code>git log </code></pre><p>3) теперь используйте</p><pre><code>git push <remotename> <commit sha>:<remotebranchname> </code></pre><p>если только одна ветка на удаленной (origin) и одна на локальной (master), просто используйте</p><pre><code>git push <commit sha> git push aa1cefc </code></pre><p>это будет push commitb и commitd.</p>