简体   繁体   中英

Pull changes from remote git repository

I'm new to git. What I have done is forked several repositories I'm interested in and then cloned them on my computer to work with them.

Some of the original projects may be significantly updated for I ever mess with my local copies, or I might make some insignificant changes.

From what I understand, I can "rebase" my clones to "pull" in the changes from the original.

What does that do to my changes? For example, suppose there is a file DoSomething.cpp from the original. I modify it, maybe fix a small bug or add a feature. Now! 1 year later the original project has gone through many revisions and is much better. I want to "pull" those changes into my clone BUT keep my change too! (so this is sort of the reverse of a push)

Is this easy to do? If so, what's the basic idea?

What I would like is that any changes in my clone from the original clone(things I've changed) are not overwritten but I can actually merge my changes and with the original(on my fork) and be given the ability to actually check and accept the changes. (for example, if DoSomething.cpp was changed on the original then I need to compare the changes to make sure they are compatible.

I guess this is not difficult since I am the owner of the fork I can rebase or hard reset it then push my local changes to my fork? (not sure if it will work though since there is a huge potential for versioning issues)

You're right, rebasing is one way you can keep your code up to date, and is very commonly used to do so.

In my experience, rebasing is more useful in terms of managing your git history. It keeps your history nice and linear, it makes it seem like the work happened sequentially rather than in parallel. Regular merges on the other hand will involve lots of diverging/converging commits. You can use git log --graph to see this difference visually.

In a nutshell, rebase takes your commits, turns them into patches, and then applies them to the branch that you're rebasing onto. If there are conflicts git will stop and ask you to resolve them, and then you can have it continue. So you're still merging and resolving conflicts, but just in a way that makes the history linear.

  1. Find out which branch you're on, this is done with git status , it'll show you the name of the branch on the first or second line.

  2. For testing, I'd suggest to first branch off your changes into a separate branch:

     git checkout -b my-patches 
  3. Now make sure that all your changes are committed. For this, you again invoke git status . Ideally it should show Working directory clean , but if thats not the case, use git add to add your changes to the index and git commit to finally commit them. If you want to split your change into several different patchsets (can be handy when conflicts occur), I suggest that you read into how to use git commit -p . You do that until all your changes are not listed in git status anymore. There will be some files you didn't touch listed in git status , possibly results of builds. If there are no changes you're interested in to keep in there, you're fine.

    If there are any makefiles or such which support cleaning up the directory ( make clean for example), run them now.

  4. Then switch back to your original branch, using (substitute master with whatever branch name you found out in step 1):

     git checkout master 

    If you want to make sure everything worked, run:

     git diff my-patches 

    It should list the lines you changed in your fork. If not, something went wrong.

  5. Now comes the scary part. You'll throw away any changes which have been made to this branch now. Note that, if you committed all your changes to the separate branch as described in step 3, they will be fine. If you're unsure, you can make a backup by copying the whole repository folder. Then you run (again, substitute master with whatever you had before):

     git fetch git reset --hard origin/master 
  6. Ideally, your branch should now have the exact state of the origin/master branch. Make sure everything looks okay. Then you merge back your changes using:

     git merge my-patches 

    Git will do it's best to make it as hassle-free as possible, but there will possibly be conflicts. Git will mark those in the respective files with >>>> and `<<<< markers. For resolving conflicts, I suggest you do some internet research or have a read on the section about Basic Merge Conflicts in the open Git Book . Make sure to commit the merge afterwards.

  7. The hard part is over. You can now delete the temporary branch:

     git branch -d my-patches 

    The reason I used the temporary branch is to be able to easily revert the status of the repository to the one before the merge attempt. One could've of course also checked out the remote status in a separate branch, but I prefer it like this.

Did you add upstream remotes to your forked repos? That's the easiest way to keep your fork in sync with it's master. It's Step 3 here .

First you should know that whether you "merge" or "rebase" you will not loose your changes and git will give you the chance to commit your changes & resolve the conflicts (if any) and then push your modifications back to the remote repo you are pulling from.

when you git pull you are telling git to do this: (pull default is to use "merge")

pull the latest copy of the files from the remote, merge them with my local changes & if there is a conflict that you couldn't resolve automatically then notify me so that I resolve it manually; it is straightforward.

when you git pull --rebase you are telling git to do this:

temporary remove* the changes from my local copy (my modified files), pull the latest copy from the remote, merge my changes on top of it & if there is a conflict that you couldn't resolve automatically then notify me so that I resolve it manually. ( technically nothing is removed; it is just to make this otherwise vague logic clearer. )

the difference is subtle, in the second case, your changes appear to be as if you have just made these changes on the top of the most recent copy that you pulled from remote... but as you could see, in both cases your changes are definitely kept (otherwise what is the use of git!).

Should you merge or rebase? it is long discussion & there are places where one is better than the other and there are best practices for this; some useful comments are already mentioned in this page and for more info you could search online, just type "git merge vs rebase" and you will see tons of pages about it : )

hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM