Git Lifecycle: Updating Your Branch with Later Development

Development may leap-frog your efforts particularly if you're engrossed in a long-term effort. If you decide you want or must take advantage of updates done by other colleagues, it is possible to git pull such code. The code can come either from the development branch or directly from a colleague's private branch.

Pulling work from branch master

Usually, when you do this, your work will collide with another's since you've both edited the same files. You'll do this:

Now your master is up-to-date with the remote copy.

Example

This example comes from Git administration (branch gitolite-admin). Trivially, I replaced one Git user's key (in subdirectory keydir) then tried to push this to the back-end repository which failed because another user had added a project to gitolite.conf then pushed that.

russ@russ-elite-book:~/swan-of-tuonela/gitolite-admin> git push To [email protected]:gitolite-admin ! [rejected] master -> master (non-fast-forward) error: failed to push some refs to '[email protected]:gitolite-admin' To prevent you from losing history, non-fast-forward updates were rejected Merge the remote changes before pushing again. See the 'Note about fast-forwards' section of 'git push --help' for details.

The solution was to git pull the changes, making my own copy up to date, then pushing all back.

russ@russ-elite-book:~/swan-of-tuonela/gitolite-admin> git pull remote: Counting objects: 7, done. remote: Compressing objects: 100% (3/3), done. remote: Total 4 (delta 1), reused 0 (delta 0) Unpacking objects: 100% (4/4), done. From swan-of-tuonela.site:gitolite-admin 69f1df9..12382af master -> origin/master Merge made by recursive. conf/gitolite.conf | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) russ@russ-elite-book:~/swan-of-tuonela/gitolite-admin> git push Counting objects: 10, done. Delta compression using up to 4 threads. Compressing objects: 100% (6/6), done. Writing objects: 100% (6/6), 965 bytes, done. Total 6 (delta 1), reused 0 (delta 0) To [email protected]:gitolite-admin 12382af..e5fc3d3 master -> master

Because the contents of gitolite.conf and subdirectory keydirs do not constitute anything difficult to merge, what Git does itself in the git pull (i.e. pull a new copy of gitolite.conf over the top of my existing one) is sufficient and no conflict is present.

In case of actual conflict, however, it would have to be resolved. This is no different than for other source code-control systems. if gitolite.conf had been edited by both of us, perhaps to add new projects, the lines might or might not be difficult to resolve. I would just use ''vim'' to merge the file. There are more intelligent tools.

Pulling work from other private branches

You may collaborate on some feature with a colleague. You (or he) might not want to contaminate the master branch with unfinished code, so you choose to pull directly from your colleague's private branch. Assume his remote branch is named hot-stuff, on the same (remote) server as yours and from a branch of the same repository (duh).

$ git remote -v origin [email protected]:rest-server (fetch) origin [email protected]:rest-server (push) $ git pull origin hot-stuff

Here's an illustration:

russ ~/acme/rest-server $ git pull origin levi remote: Counting objects: 126, done. remote: Compressing objects: 100% (78/78), done. remote: Total 95 (delta 37), reused 0 (delta 0) Unpacking objects: 100% (95/95), done. From acme.site:rest-server * branch levi -> FETCH_HEAD Auto-merging .classpath CONFLICT (content): Merge conflict in .classpath Auto-merging WebContent/WEB-INF/web.xml CONFLICT (content): Merge conflict in WebContent/WEB-INF/web.xml Auto-merging src/com/acme/user/entity/AccountRepository.java CONFLICT (content): Merge conflict in src/com/acme/user/entity/AccountRepository.java Auto-merging src/com/acme/user/entity/Language.java CONFLICT (content): Merge conflict in src/com/acme/user/entity/Language.java Auto-merging src/com/acme/user/entity/LanguageRepository.java CONFLICT (add/add): Merge conflict in src/com/acme/user/entity/LanguageRepository.java Auto-merging src/com/acme/user/manager/LanguageManager.java CONFLICT (content): Merge conflict in src/com/acme/user/manager/LanguageManager.java Auto-merging src/com/acme/user/service/AccountWS.java CONFLICT (content): Merge conflict in src/com/acme/user/service/AccountWS.java Auto-merging src/com/acme/user/service/LanguageWS.java CONFLICT (content): Merge conflict in src/com/acme/user/service/LanguageWS.java Auto-merging src/resources/jdbc.properties CONFLICT (add/add): Merge conflict in src/resources/jdbc.properties Auto-merging src/resources/spring-configuration.xml CONFLICT (add/add): Merge conflict in src/resources/spring-configuration.xml Automatic merge failed; fix conflicts and then commit the result. master ~/acme/rest-server $ gvim .classpath

etc... until I resolved all the conflicts (using Vim).

russ ~/acme/rest-server $ git add .classpath WebContent/WEB-INF/web.xml \ src/com/acme/user/entity/AccountRepository.java src/com/acme/user/entity/Language.java \ src/com/acme/user/entity/LanguageRepository.java src/com/acme/user/manager/LanguageManager.java \ src/com/acme/user/service/LanguageWS.java src/com/acme/user/service/AccountWS.java \ src/resources/jdbc.properties src/resources/spring-configuration.xml russ ~/acme/rest-server $ git commit [russ 0f2fd80] Merge branch 'levi' of acme.site:rest-server into russ russ ~/acme/rest-server $

Reciprocal usernames

It's a suggestion that each developer set up a ''git-user'' on his or her local host. Under /home/git-user/.ssh, concatenate each colleague's private RSA key to authorized_keys. This makes it so that your colleague need not type a password when performing the ''git pull'' command above. This procedure is detailed more fully in Setting up SSH keys.

Pulling from master branch, a live example

I work with a colleague, Levi, who has just merged his changes into master branch and pushed them out to remote. I want to get those changes as they're officially (hence master) what's to be in the product. This is early in the morning; I had already committed all my final work last night and have done nothing this morning. Levi merged his changes this morning, so I'll have nothing that's not fast-forwarded. Therefore, this is the easy case.

Here's what I (Russ) did to accomplish this. These steps are recorded in the console scrap after the list here.

  1. Check out master branch.
  2. Pull changes committed to remote master down to my own local copy of master.
  3. Check out russ branch.
  4. Merge changes from master into russ.

(Note: the green branch name in my prompt is a function of special bash code that creates it. See How to remember what Git branch I'm working in (2).)

russ ~/acme/rest-server $ git checkout master Switched to branch 'master' master ~/acme/rest-server $ git pull remote: Counting objects: 27, done. remote: Compressing objects: 100% (15/15), done. remote: Total 17 (delta 10), reused 0 (delta 0) Unpacking objects: 100% (17/17), done. From acme.site:rest-server 4b85a48..7e9d6de levi -> origin/levi b503cea..7e9d6de master -> origin/master Updating b503cea..7e9d6de Fast-forward ....acme.user.manager.AccountManagerUnitTest.xml | 103 ++++++++++++++++++++ .classpath | 2 + build.xml | 17 ++-- lib/apache/httpclient-4.1.3.jar | Bin 0 -> 352585 bytes 4 files changed, 114 insertions(+), 8 deletions(-) create mode 100644 build/cobertura/cobertura_test_reports/TEST-com.acme.user.manager.AccountManagerUnitTest.xml create mode 100644 lib/apache/httpclient-4.1.3.jar master ~/acme/rest-server $ git checkout russ Switched to branch 'russ' russ ~/acme/rest-server $ git merge master Updating b503cea..7e9d6de Fast-forward ....acme.user.manager.AccountManagerUnitTest.xml | 103 ++++++++++++++++++++ .classpath | 2 + build.xml | 17 ++-- lib/apache/httpclient-4.1.3.jar | Bin 0 -> 352585 bytes 4 files changed, 114 insertions(+), 8 deletions(-) create mode 100644 build/cobertura/cobertura_test_reports/TEST-com.acme.user.manager.AccountManagerUnitTest.xml create mode 100644 lib/apache/httpclient-4.1.3.jar russ ~/acme/rest-server $ git push Total 0 (delta 0), reused 0 (delta 0) To [email protected]:rest-server b503cea..7e9d6de russ -> russ

Pulling from master branch, a more complicated example

Here's a similar experience, but one with conflicts.

russ ~/acme/rest-server $ git checkout master Switched to branch 'master' master ~/acme/rest-server $ git pull remote: Counting objects: 138, done. remote: Compressing objects: 100% (95/95), done. remote: Total 111 (delta 54), reused 0 (delta 0) Receiving objects: 100% (111/111), 910.35 KiB, done. Resolving deltas: 100% (54/54), completed with 20 local objects. From acme.site:rest-server 8669e13..781bdd5 levi -> origin/levi + a1e8a54...781bdd5 master -> origin/master (forced update) Auto-merging .classpath CONFLICT (content): Merge conflict in .classpath Auto-merging src/com/acme/user/service/AccountWS.java CONFLICT (content): Merge conflict in src/com/acme/user/service/AccountWS.java Automatic merge failed; fix conflicts and then commit the result. master ~/acme/rest-server $ gvim .classpath master ~/acme/rest-server $ gvim src/com/acme/user/service/AccountWS.java master ~/acme/rest-server $ git push To [email protected]:rest-server ! [rejected] master -> master (non-fast-forward) error: failed to push some refs to '[email protected]:rest-server' To prevent you from losing history, non-fast-forward updates were rejected Merge the remote changes before pushing again. See the 'Note about fast-forwards' section of 'git push --help' for details. master ~/acme/rest-server $ git status # On branch master # Your branch and 'origin/master' have diverged, # and have 4 and 8 different commit(s) each, respectively. # # Changes to be committed: # # new file: extras/schema/postgres/auth-table.sql # modified: extras/schema/postgres/schema.sql # modified: extras/schema/postgres/test-data.sql # new file: lib/apache/commons-collections-3.2.1.jar # modified: src/com/acme/user/entity/Account.java # new file: src/com/acme/user/entity/Auth.java # modified: src/com/acme/user/manager/AccountManager.java # new file: src/com/acme/user/manager/AuthManager.java # new file: src/com/acme/user/service/AuthWS.java # modified: src/resources/hibernate.cfg.xml # modified: src/resources/hibernate.psyg.cfg.xml # # Unmerged paths: # (use "git add/rm <file>..." as appropriate to mark resolution) # # both modified: .classpath # both modified: src/com/acme/user/service/AccountWS.java # master ~/acme/rest-server $ git add .classpath src/com/acme/user/service/AccountWS.java master ~/acme/rest-server $ git commit [master 23aecd7] Merge branch 'master' of acme.site:rest-server master ~/acme/rest-server $ git push Counting objects: 28, done. Delta compression using up to 4 threads. Compressing objects: 100% (8/8), done. Writing objects: 100% (10/10), 1.12 KiB, done. Total 10 (delta 4), reused 0 (delta 0) To [email protected]:rest-server 781bdd5..23aecd7 master -> master russ ~/acme/rest-server $ git checkout russ Switched to branch 'russ' russ ~/acme/rest-server $ git merge master Updating a1e8a54..23aecd7 Fast-forward .classpath | 10 +- extras/schema/postgres/auth-table.sql | 13 + extras/schema/postgres/schema.sql | 1 + extras/schema/postgres/test-data.sql | 6 +- lib/apache/commons-collections-3.2.1.jar | Bin 0 -> 575389 bytes src/com/acme/user/entity/Account.java | 314 ++++++++++++++--------- src/com/acme/user/entity/Auth.java | 153 +++++++++++ src/com/acme/user/manager/AccountManager.java | 117 +++++++-- src/com/acme/user/manager/AuthManager.java | 224 ++++++++++++++++ src/com/acme/user/service/AccountWS.java | 231 +++++++++++------ src/com/acme/user/service/AuthWS.java | 302 ++++++++++++++++++++++ src/resources/hibernate.cfg.xml | 8 +- src/resources/hibernate.psyg.cfg.xml | 3 +- 13 files changed, 1149 insertions(+), 233 deletions(-) create mode 100644 extras/schema/postgres/auth-table.sql create mode 100644 lib/apache/commons-collections-3.2.1.jar create mode 100644 src/com/acme/user/entity/Auth.java create mode 100644 src/com/acme/user/manager/AuthManager.java create mode 100644 src/com/acme/user/service/AuthWS.java russ ~/acme/rest-server $ git push Total 0 (delta 0), reused 0 (delta 0) To [email protected]:rest-server a1e8a54..23aecd7 russ -> russ

Another complex example

The order in which I'm doing things is probably something to retain.

I updated files while my colleagu, Levi, also updated files. He committed before I. I committed to branch russ and pushed to my remote. Then, I checked out master and pulled what was in master's remote (what Levi had committed and pushed earlier). Then, I returned to russ and merged master into it, pushed to my remote, then merged my changes into master and pushed them to master's remote.

russ ~/acme/rest-server $ git commit [russ ea82db1] Rid us of all the ids for what is better supported as ISO two-letter country and state codes (and \ also our invented continent codes). Some additional polishing. 12 files changed, 539 insertions(+), 532 deletions(-) rewrite extras/schema/continent-data.sql (80%) rewrite extras/schema/country-data.sql (98%) rewrite extras/schema/state-data.sql (93%) russ ~/acme/rest-server $ git push Counting objects: 43, done. Delta compression using up to 4 threads. Compressing objects: 100% (20/20), done. Writing objects: 100% (22/22), 8.65 KiB, done. Total 22 (delta 11), reused 0 (delta 0) To [email protected]:rest-server ca36db2..ea82db1 russ -> russ ! [rejected] master -> master (non-fast-forward) error: failed to push some refs to '[email protected]:rest-server' To prevent you from losing history, non-fast-forward updates were rejected Merge the remote changes before pushing again. See the 'Note about fast-forwards' section of 'git push --help' for details. russ ~/acme/rest-server $ git checkout master Switched to branch 'master' master ~/acme/rest-server $ git pull remote: Counting objects: 128, done. remote: Compressing objects: 100% (71/71), done. remote: Total 76 (delta 54), reused 0 (delta 0) Unpacking objects: 100% (76/76), done. From acme.site:rest-server ca36db2..07ed272 master -> origin/master Updating ca36db2..07ed272 Fast-forward .classpath | 10 ++ lib/aspectj/aspectjrt.jar | Bin 0 -> 116219 bytes lib/aspectj/aspectjweaver.jar | Bin 0 -> 1749970 bytes src/com/acme/oauth/service/OAuthServerWS.java | 2 +- src/com/acme/oauth/service/OAuthWS.java | 2 +- src/com/acme/user/entity/AccountRepository.java | 2 +- src/com/acme/user/entity/AddressRepository.java | 2 +- .../acme/user/entity/AddressTypeRepository.java | 2 +- src/com/acme/user/entity/AuthRepository.java | 95 +------------------- src/com/acme/user/entity/CardTypeRepository.java | 2 +- .../acme/user/entity/CheckPaymentRepository.java | 2 +- .../acme/user/entity/ContinentRepository.java | 2 +- src/com/acme/user/entity/CountryRepository.java | 2 +- .../acme/user/entity/CreditCardRepository.java | 2 +- .../acme/user/entity/DebitCardRepository.java | 2 +- src/com/acme/user/entity/LanguageRepository.java | 2 +- src/com/acme/user/entity/PaymentRepository.java | 2 +- src/com/acme/user/entity/StateRepository.java | 2 +- src/com/acme/user/manager/AccountManager.java | 2 +- src/com/acme/user/manager/AddressManager.java | 2 +- .../acme/user/manager/AddressTypeManager.java | 2 +- src/com/acme/user/manager/AuthManager.java | 84 +++++++++++++---- src/com/acme/user/manager/CardTypeManager.java | 2 +- .../acme/user/manager/CheckPaymentManager.java | 2 +- src/com/acme/user/manager/ContinentManager.java | 2 +- src/com/acme/user/manager/CountryManager.java | 2 +- src/com/acme/user/manager/CreditCardManager.java | 2 +- src/com/acme/user/manager/DebitCardManager.java | 2 +- src/com/acme/user/manager/LanguageManager.java | 2 +- src/com/acme/user/manager/PaymentManager.java | 2 +- src/com/acme/user/manager/StateManager.java | 2 +- src/com/acme/user/service/AccountWS.java | 2 +- src/com/acme/user/service/AddressTypeWS.java | 2 +- src/com/acme/user/service/AddressWS.java | 2 +- src/com/acme/user/service/AuthWS.java | 84 +---------------- src/com/acme/user/service/CardTypeWS.java | 2 +- src/com/acme/user/service/CheckPaymentWS.java | 2 +- src/com/acme/user/service/ContinentWS.java | 2 +- src/com/acme/user/service/CountryWS.java | 2 +- src/com/acme/user/service/CreditCardWS.java | 2 +- src/com/acme/user/service/DebitCardWS.java | 2 +- src/com/acme/user/service/LanguageWS.java | 2 +- src/com/acme/user/service/PaymentWS.java | 2 +- src/com/acme/user/service/StateWS.java | 2 +- src/com/acme/user/util/AspectLogger.java | 40 ++++++++ src/com/acme/user/util/HibernateUtil.java | 2 +- .../acme/user/util/MongoConnectionManager.java | 2 +- src/com/acme/user/util/SharedSecurityFilter.java | 2 +- src/com/acme/user/util/SystemConfiguration.java | 2 +- src/log4j.properties | 2 +- src/resources/spring-configuration.xml | 11 ++- 51 files changed, 174 insertions(+), 236 deletions(-) create mode 100644 lib/aspectj/aspectjrt.jar create mode 100644 lib/aspectj/aspectjweaver.jar create mode 100644 src/com/acme/user/util/AspectLogger.java master ~/acme/rest-server $ git checkout russ Switched to branch 'russ' russ ~/acme/rest-server $ git merge master Merge made by recursive. .classpath | 10 ++ lib/aspectj/aspectjrt.jar | Bin 0 -> 116219 bytes lib/aspectj/aspectjweaver.jar | Bin 0 -> 1749970 bytes src/com/acme/oauth/service/OAuthServerWS.java | 2 +- src/com/acme/oauth/service/OAuthWS.java | 2 +- src/com/acme/user/entity/AccountRepository.java | 2 +- src/com/acme/user/entity/AddressRepository.java | 2 +- .../acme/user/entity/AddressTypeRepository.java | 2 +- src/com/acme/user/entity/AuthRepository.java | 95 +------------------- src/com/acme/user/entity/CardTypeRepository.java | 2 +- .../acme/user/entity/CheckPaymentRepository.java | 2 +- .../acme/user/entity/ContinentRepository.java | 2 +- src/com/acme/user/entity/CountryRepository.java | 2 +- .../acme/user/entity/CreditCardRepository.java | 2 +- .../acme/user/entity/DebitCardRepository.java | 2 +- src/com/acme/user/entity/LanguageRepository.java | 2 +- src/com/acme/user/entity/PaymentRepository.java | 2 +- src/com/acme/user/entity/StateRepository.java | 2 +- src/com/acme/user/manager/AccountManager.java | 2 +- src/com/acme/user/manager/AddressManager.java | 2 +- .../acme/user/manager/AddressTypeManager.java | 2 +- src/com/acme/user/manager/AuthManager.java | 84 +++++++++++++---- src/com/acme/user/manager/CardTypeManager.java | 2 +- .../acme/user/manager/CheckPaymentManager.java | 2 +- src/com/acme/user/manager/ContinentManager.java | 2 +- src/com/acme/user/manager/CountryManager.java | 2 +- src/com/acme/user/manager/CreditCardManager.java | 2 +- src/com/acme/user/manager/DebitCardManager.java | 2 +- src/com/acme/user/manager/LanguageManager.java | 2 +- src/com/acme/user/manager/PaymentManager.java | 2 +- src/com/acme/user/manager/StateManager.java | 2 +- src/com/acme/user/service/AccountWS.java | 2 +- src/com/acme/user/service/AddressTypeWS.java | 2 +- src/com/acme/user/service/AddressWS.java | 2 +- src/com/acme/user/service/AuthWS.java | 84 +---------------- src/com/acme/user/service/CardTypeWS.java | 2 +- src/com/acme/user/service/CheckPaymentWS.java | 2 +- src/com/acme/user/service/ContinentWS.java | 2 +- src/com/acme/user/service/CountryWS.java | 2 +- src/com/acme/user/service/CreditCardWS.java | 2 +- src/com/acme/user/service/DebitCardWS.java | 2 +- src/com/acme/user/service/LanguageWS.java | 2 +- src/com/acme/user/service/PaymentWS.java | 2 +- src/com/acme/user/service/StateWS.java | 2 +- src/com/acme/user/util/AspectLogger.java | 40 ++++++++ src/com/acme/user/util/HibernateUtil.java | 2 +- .../acme/user/util/MongoConnectionManager.java | 2 +- src/com/acme/user/util/SharedSecurityFilter.java | 2 +- src/com/acme/user/util/SystemConfiguration.java | 2 +- src/log4j.properties | 2 +- src/resources/spring-configuration.xml | 11 ++- 51 files changed, 174 insertions(+), 236 deletions(-) create mode 100644 lib/aspectj/aspectjrt.jar create mode 100644 lib/aspectj/aspectjweaver.jar create mode 100644 src/com/acme/user/util/AspectLogger.java russ ~/acme/rest-server $ git status # On branch russ nothing to commit (working directory clean) russ ~/acme/rest-server $ git push Counting objects: 22, done. Delta compression using up to 4 threads. Compressing objects: 100% (6/6), done. Writing objects: 100% (8/8), 858 bytes, done. Total 8 (delta 2), reused 0 (delta 0) To [email protected]:rest-server ea82db1..7f3d1de russ -> russ russ ~/acme/rest-server $ git checkout master Switched to branch 'master' master ~/acme/rest-server $ git merge russ Updating 07ed272..7f3d1de Fast-forward extras/schema/address-table.sql | 6 +- extras/schema/continent-data.sql | 28 +- extras/schema/continent-table.sql | 7 +- extras/schema/country-data.sql | 498 ++++++++++++++-------------- extras/schema/country-table.sql | 9 +- extras/schema/state-data.sql | 270 ++++++++-------- extras/schema/state-table.sql | 9 +- extras/schema/test-data.sql | 34 ++- src/com/acme/user/entity/Address.java | 72 ++--- src/com/acme/user/entity/Continent.java | 8 +- src/com/acme/user/entity/Country.java | 20 +- src/com/acme/user/entity/State.java | 24 +- 12 files changed, 496 insertions(+), 489 deletions(-) master ~/acme/rest-server $ git push Total 0 (delta 0), reused 0 (delta 0) To [email protected]:rest-server 07ed272..7f3d1de master -> master