web-dev-qa-db-fra.com

Comment pouvez-vous pousser seulement certains de vos commits git locaux?

Supposons que j'ai 5 commits locaux. Je souhaite n'en envoyer que 2 à un référentiel centralisé (en utilisant un workflow de style SVN). Comment puis-je faire cela?

Cela n'a pas fonctionné:

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

Cela finit par pousser les 5 commits locaux.

Je suppose que je pourrais faire git reset pour annuler réellement mes commits, suivi de git stash puis git Push - mais j'ai déjà écrit des messages de commit et des fichiers organisés et je ne veux pas les refaire.

Mon sentiment est qu'un drapeau passé à Push ou reset fonctionnerait.

Si ça aide, voici ma configuration 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
136
ramanujan

En supposant que vos validations se trouvent sur la branche principale et que vous souhaitez les envoyer à la branche principale distante:

$ git Push Origin master~3:master

Si vous utilisiez git-svn:

$ git svn dcommit master~3

Dans le cas de git-svn, vous pouvez également utiliser HEAD ~ 3, car il attend un commit. Dans le cas de git simple, vous devez utiliser le nom de la branche car HEAD n'est pas évalué correctement dans la refspec.

Vous pouvez également adopter une approche plus longue de:

$ git checkout -b tocommit HEAD~3
$ git Push Origin tocommit:master

Si vous prenez l'habitude de ce type de flux de travail, vous devriez envisager de faire votre travail dans une branche distincte. Ensuite, vous pourriez faire quelque chose comme:

$ git checkout master
$ git merge working~3
$ git Push Origin master:master

Notez que la partie "Origin master: master" est probablement facultative pour votre configuration.

173
Ryan Graham

Ce que je fais, c'est travailler sur une branche locale appelée "travail". Cette branche contient toutes les validations temporaires (comme des solutions de contournement ou des options de construction privées ou autre) que je n'ai pas l'intention de pousser vers le référentiel en amont. Je travaille loin sur cette branche, puis lorsque je veux valider, je passe à la branche principale, je sélectionne les commits appropriés que je veux vouloir valider , puis Push master.

Après avoir tiré les modifications de l'amont vers ma branche principale, je git checkout work et git rebase master. Cela réécrit tous mes changements locaux pour être à la fin de l'histoire.

J'utilise en fait git svn avec ce flux de travail, donc mon opération "Push" implique git svn dcommit. J'utilise également tig qui est une visionneuse de référentiel gui en mode texte agréable, pour sélectionner les commits appropriés à maîtriser.

16
Greg Hewgill

Par défaut, git-Push pousse toutes les branches. Lorsque vous faites cela:

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

Vous vous déplacez vers un HEAD (vous n'êtes sur aucune branche) détaché, puis vous poussez toutes les branches, y compris le maître local (qui est toujours là où il était) vers le maître distant.

La solution manuelle est:

 git Push Origin HEAD:master

Si vous trouvez le comportement par défaut de pousser toutes les branches déroutant (et dangereux!), Ajoutez ceci à votre ~/.gitconfig:

 [remote.Origin]
    Push = HEAD

Ensuite, seule la branche sur laquelle vous vous trouvez est poussée. Dans votre exemple (une tête détachée), vous auriez eu ce message d'erreur, plutôt que de pousser accidentellement les mauvais commits:

 error: unable to Push to unqualified destination: HEAD
13
Thomas Leonard

Réponse courte:

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

Exemples:

git Push fc47b2

git Push HEAD~2

Longue réponse:

Les validations sont liées entre elles comme une chaîne avec un mécanisme parent/enfant. Ainsi, pousser un commit pousse également tous les commit parents à ce commit qui n'était pas connu de la télécommande. Cela se fait implicitement lorsque vous git Push le commit actuel: tous les commits précédents sont également poussés car cette commande est équivalente à git Push HEAD.

Ainsi, la question pourrait être réécrite en Comment pousser un commit spécifique et ce commit spécifique pourrait être HEAD ~ 2, par exemple.

Si les validations que vous souhaitez pousser ne sont pas consécutives, il vous suffit de les réorganiser avec un git rebase -i avant le Push spécifique.

6
Tim

1) Utilisez "git rebase" pour réorganiser vos commits, si vous le souhaitez.

git rebase -i

Cette commande affichera quelque chose comme ça dans votre éditeur (j'utilise 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) Réorganisez vos commits selon votre choix par simple pâte coupée. Supposons que la nouvelle commande soit

pick 9781434 commitE

choisissez c3d4961 commitC

pick 4791291 commitA

choisissez aa1cefc commitD

choisissez a2bdfbd commitB

Apportez ces modifications dans votre éditeur et appuyez sur ctrl + O (writeOut)

Ou vous pouvez également utiliser

git rebase -i HEAD~<commitNumber>

Vous pouvez vérifier la nouvelle séquence avec

git log

3) Utilisez maintenant

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

Si une seule branche à distance (origine) et une au niveau local (maître), utilisez simplement

git Push <commit SHA>
git Push aa1cefc

Cela poussera commitB et commitD.

4
shiva