What are the differences between "git commit" and "git push"?
In a Git tutorial I'm going through, git commit
is used to store the changes you've made.
What 开发者_如何学运维is git push
used for then?
Basically, git commit
"records changes to the repository" while git push
"updates remote refs along with associated objects". So the first one is used in connection with your local repository, while the latter one is used to interact with a remote repository.
Here is a nice picture from Oliver Steele, that explains the Git model and the commands:
Read more about git push
and git pull
on Pushing and pulling (the article I referred to first).
commit: adding changes to the local repository
push: to transfer the last commit(s) to a remote server
Well, basically Git commit puts your changes into your local repository, while git push sends your changes to the remote location.
git push
is used to add commits you have done on the local repository to a remote one. Together with git pull
, it allows people to collaborate.
Commit: Snapshot | Changeset | Version | History-record | 'Save-as' of a repository. Git repository = series (tree) of commits.
Local repository: repository on your computer.
Remote repository: repository on a server (GitHub).
git commit
: Append a new commit (last commit + staged modifications) to the local repository. (Commits are stored in folder /.git
.)
git push
, git pull
: Sync the local repository with its associated remote repository. push
- apply changes from local into remote, pull
- apply changes from remote into local.
Since Git is a distributed version control system, the difference is that commit will commit changes to your local repository, whereas push will push changes up to a remote repository.
git commit
record your changes to the local repository.
git push
update the remote repository with your local changes.
Three things to note:
Working directory — folder where our code files are present
Local repository — This is inside our system. When we do the commit command the first time, then this local repository is created in the same place where our working directory is. Checkit (.git) file get created. After that whenever we do commit, this will store the changes we make in the file of the working directory to the local repository (.git).
Remote repository — This is situated outside our system like on servers located any where in the world, like GitHub. When we make a push command then code from our local repository gets stored at this remote repository.
Just want to add the following points:
Yon can not push until you commit as we use git push
to push commits made on your local branch to a remote repository.
The git push
command takes two arguments:
A remote name, for example, origin
A branch name, for example, master
For example:
git push <REMOTENAME> <BRANCHNAME>
git push origin master
A very crude analogy: if we compare git commit
to saving an edited file, then git push
would be copying that file to another location.
Please don't take this analogy out of this context -- committing and pushing are not quite like saving an edited file and copying it. That said, it should hold for comparisons sake.
A Common Sense Explanation of How Git Works
I have been using Git for years, but oddly enough nobody here or online seems to be able to explain in simple terms how Git's push
, pull
, commit
, or pull requests
really work. So, below is a simple explanation. I hope it explains things more clearly. It helped me!
A SIMPLE SUMMARY OF HOW GIT WORKS
In Git, you always create code on your local computer first and then save your code into Git's "local repository" (repo) on your computer. You then upload your changes to Git's shared "remote repository" when you are done so others can access your code changes. You also download changes from the "remote repository" to your "local repository" so your code stays up-to-date with other developer's changes. You then start the process all over again.
In this way, Git allows you to share your local project code with others remotely while saving versions of those code changes in case something goes wrong and you have to redo some bad code. That's the simple explanation of how Git works and the cycle of how it is used.
MORE GIT DETAILS
The first step is always writing code on your local computer, ignoring Git which is not involved in saving or testing code in any way. When you save your local code on your computer, it is not saved in Git by default like you think. You have to do a second step called a "commit". (Saved code that is not commited yet is called "staged" code, btw.)
A commit
is the same as saving your local code changes but in the 'Git world'. This confuses people. But when I see the word "commit" I think of it as a "Git Save". It's an extra step, because you already saved your code changes once, and now have to save them a second time in the Git system as a commit or they do not become part of your local Git repository system. I think "commits" are one reason some think Git is poorly designed. It just is not intuitive.
A push
is done after you have finished all your code saves and commited your code to your Git repo locally. The push command sends your local repository changes (commits only) up to a remote repository so it is updated. When it does this it writes 100% of your changes over the remote repository completely so the two are in sync or the code matches 100% between the two. Think of this as a "Remote Git Save". It writes over the code on the remote repo with what you have locally on your computer. This made no sense to me at first. Would that not erase changes by other developers on the remote? What if the remote conflicts with your changes or you do not have changes in the remote you need first in your local repo? This confused me at first as no one could explain online if this was the same as a "merge", a "commit", "pull request", etc. It turns out this ONLY works under ONE CONDITION. Otherwise it blocks your push and fails!
A "push" only works if you are the only person changing the remote repo and the two code bases are the same other than the commits you added locally. Otherwise, any changes made by another user on that remote will cancel your push. So think of push
as a "Private Remote Write Over" of the same copy as on your local rep. But we know many developers will be pushing changes to the remote copy same as you with pushes, right? So push would fail and everyone would be constantly out of synch on their local copy with the remote copy under this design.
As I mentioned, this push is ONLY allowed (not blocked on the remote repo) if the remote repository is in the exact state as your local repository BEFORE you made changes. In other words, you can only push your local change to the remote project and completely write over it with a push
if the remote repo has not been modified by any other developer when you push commit local changes up. That is one weird aspect of Git that confuses people. If your local copy of code is out of sync in any way with the remote repo because it has been changed, the push will fail and you will be forced to do a pull
or "rebase" which is a fancy word for "update your local repo first with the remote copy". If your push is blocked and you then do a pull
, it will copy down the remote code and "merge" its code changes into your local copy. Once in sync again, you can still push your commits up with a push as they should still be present after the pull or merge.
This works perfectly in most cases unless a code change conflicts with commits or code changes you made the other developer also made in the same code area. In that rare case you have to resolve the conflict locally before you can proceed with anything else, as you could erase another developers changes with your own by accident. That is where pull requests
(see below) are helpful instead of a push, as the former forces major code changes to be resolved on the remote copy manually by the code owners or admins first before any code is allowed to change the remote repo.
Interestingly, a "pull" does the same as a "push", but in this case pulls a copy of the latest remote project down to your local git system then "merges" those changes into your own copy, not write over them like a "push" does. Of course, this syncs your remote and local copies again, minus the new commits you are set to update on the remote repo using your "push" again.
Once you have sync'ed your local copy to remote via a pull
, you can now do a push
and send your commits
or changes back up to the remote copy again and write over it safely knowing you have merged your changes with the ones made by all the other developers.
After the push
writes over the remote copy with your local copy's commits or changes, the remote matches your local copy exactly. Because they both match, any additional commits or saves you make locally can be pushed again remotely without pulls - as long as no developers have changed the remote like you have. Git will always alert you on pushes if that is the case. You cannot screw it up. You can do "forced" pushes., "rebasing", and other tricks but that's not important. But as soon as other developers push their changes, you are out of sync again and have to do a pull again first before pushing.
This commit-pull-push is the real rhythm of Git development nobody tells you about and assumes you understand. Most do not. It just is not intuitive or logical.
Of course you can "force" a push and write over everything anyway. But this system will alert you before you try that. This system of pulls and pushes always works better when one developer is updating one branch in one remote repository they own. It fails as soon as a new person adds or changes anything in the remote. That is what causes pushes and pull alerts and failures until everyone sync's again with the remote. When that is done, the developer has power to push changes as their code matches the remote again. But its better to use the Git pull request
command when there are a lot of changes or merges of branches and code going to remote repo's.
Lastly, it is important to note that people developing in Git are almost always encouraged to create a new local and remote repo branch first before making changes to software. In that case, the push
and pull
makes perfect sense as code changes are then almost always done on an isolated branch of the software by a single developer who never conflicts with other developer changes. This then explains why its common for one developer to work on their own branch, and in that case, push
and pull
works perfectly, can push/pull changes quickly, never causes code conflicts, and allows the one developer to store copies of their final local changes on a remote repo branch he pushes for merging later into main branches using the pull request
system described below.
The Weird Pull Request
Last part of the Git puzzle. A pull request
is a "pull" from the perspective of the remote repository pulling local repo code up into it. But it is a request and initially does NOT physically pull anything or change anything, nor push or merge any code. It is simply a request you send to a remote repo from your local repo to review code and if they approve, pull your code into their remote copy.
In a pull request
, you are asking the remote repo admins or owners to upload your code changes or commits, review your local repo commit changes, and then merge your code changes into the remote repo upon their approval. When they approve of your reviewed local repo commits or changes, they pull your local repo code or branch and merge it into a remote repo branch.
The remote repo has admins or owners that control critical top branches of code in the remote repo that are being prepared for production. They do not like to merge changes of code into these larger branches without some control over the quality of the code. When you do a pull request
you are alerting the admin or remote repo owners that you as a local developer have some finished branch of code and want them to manually pull your local repo code up into the remote repo code. This is the same as a push
from a local to a remote repo, but in this case requires it be completed from the opposite direction by top remote repo owners. It also requires a manual code review and approval of changes from the remote repo owners, first.
Note: It is more common for a pull request
to merge code between two remote repo branches, and usually affects finished branches of code on the remote server or device that must be merged into a main remote branch, not just local commit changes. Again, not intuitive, but there you go!
Why would you need a pull request if you have push
and pull
Git commands synchronizing and merging code? pull requests
work better than pushes in scenarios where lots and lots of people are pulling and pushing huge changes to finished branches with merges to the main remote repo branches and where lots of code could conflict or code added that must be tested or code reviewed first before going to a major release or code base update. Push
and 'Pull' works better for isolated smaller branches only one or two developers are working on and sharing. It is much easier to pull
and push
code between local and remote repos than to merge massive branches of complex remote repo changes into the master branches of a remote repo.
So rememeber...
Use 'Push' to update small branches you control both locally and remotely.
Use 'Pull Request' to have remote repository people merge your smaller branches into their larger ones on the remote servers.
So I like to think of pull requests
as a Master Push and a push
as a Local Push. I wish the Git guys had made the names for these processes more logical and easier to understand. It just is not intuitive at all!
It turns out a pull request
is also a way of adding a layer of code security that asks permission by admins or team members first when merging large stacks of code into critical top level remote
branches or merges of branches in projects. As such it asks the team members to approve large batches of local repo code changes and commits first before they pull them into important remote repo branches.
This serves to protect code updates to critical branches with code reviews and approvals first. But it also allows remote repos being updated by lots of teams to pause code changes on more important branches and merges before they are tested, approved, etc. This is why small branches of code private to a developer are simply pull and push changes, but larger merges of those branches are typically blocked from pushes by pull requests instead. This is more typical of finished branches using pushes that are then merged into larger branches up the Git tree.
Figuring this out took hours and hours of research, even after I had been using Git for years, since there is no documentation online explaining this difference.
So....always use a commit-pull-push routine when working on your own code changes or sections of projectss assigned to you. Pull down repos first to make sure your local repo has all the latest changes made to it by other developers. Commit or save all your local changes before and after the pull if you like...it doesn't matter. If there are conflicts, try to resolve them locally. Then and only then, do your push to write over the remote copy with your local code. Your local and remote repositories are then 100% in sync in the Git World!
Lastly, when your local and remote branches are done, send a pull request to your git administrator and have them handle the merge of your completed remote repository branch.
It is easier to understand the use of the Git commands add
and commit
if you imagine a log file being maintained in your repository on GitHub.
A typical project's log file for me may look like:
---------------- Day 1 --------------------
Message: Completed Task A
Index of files changed: File1, File2
Message: Completed Task B
Index of files changed: File2, File3
-------------------------------------------
---------------- Day 2 --------------------
Message: Corrected typos
Index of files changed: File3, File1
-------------------------------------------
...
...
...and so on
I usually start my day with a git pull
request and end it with a git push
request. So everything inside a day's record corresponds to what occurs between them. During each day, there are one or more logical tasks that I complete which require changing a few files. The files edited during that task are listed in an index.
Each of these sub tasks (Task A and Task B here) are individual commits. The git add
command adds files to the 'Index of Files Changed' list. This process is also called staging and in reality records changed files and the changes performed. The git commit
command records/finalizes the changes and the corresponding index list along with a custom message which may be used for later reference.
Remember that you're still only changing the local copy of your repository and not the one on GitHub. After this, only when you do a git push
do all these recorded changes, along with your index files for each commit, get logged on the main repository (on GitHub).
As an example, to obtain the second entry in that imaginary log file, I would have done:
git pull
# Make changes to File3 and File4
git add File3 File4
# Verify changes, run tests etc..
git commit -m 'Corrected typos'
git push
In a nutshell, git add
and git commit
lets you break down a change to the main repository into systematic logical sub-changes. As other answers and comments have pointed out, there are of course many more uses to them. However, this is one of the most common usages and a driving principle behind Git being a multi-stage revision control system unlike other popular ones like SVN.
Git commit is nothing but saving our changes officially. For every commit we give commit message, and once we are done with commits we can push it to remote to see our change globally.
Which means we can do numerous commits before we push to remote (we can see the list of commits happened and the messages too). Git saves each commit with commit id which is a 40 digit code.
And I used Git push only when I wanted to see my change in remote (thereafter I will check whether my code worked in Jenkins).
When you commit your changes, you save the changes as a single logical set in your local repository. You can do this multiple times without pushing. Until they are pushed, they do not leave your local repository meaning the remote repository won't have these sets of changes yet, so when other people pull from the remote repository, your commits won't be pulled.
When you push, all the commits you made in your local repository will be transferred to the remote repository, so when other developers who share this remote repository pull, they will have your changes transferred to their local repositories. Check Git commands and a cheat sheet here.
git commit
is to commit the files that are staged in the local repository. git push
is to fast-forward merge the master branch of local side with the remote master branch. But the merge won't always succeed. If rejection appears, you have to pull
so that you can make a successful git push
.
精彩评论