234

We recently switched from SVN to Git and at the same time put our live systems into version control (instead of local checkout and file copy to live).

On the project I'm assigned to we all access the same repository and to get changes into live we just git pull there. This causes problems because our web designers push changes into the VCS that should not be live yet but should be on the web-testing environment.

When one of the developers now pulls into live he gets all (possibly unfinished) changes.

I thought of switching live to an extra branch and just merge what changed but due to my lack of git knowledge I have no idea how.

My idea is:

  • Create a new branch in live (git branch live).
  • Every time something has to go live
    • Pull changes in master (like: git checkout master; git pull; git checkout live)
    • git merge master

The problem is that switching to master or pulling everything directly into the live system would cause problems so I'd prefer to avoid this.

Is there any way to do this or is there any better way to manage the live system (except for training the webbies to not push unfinished stuff)?

John Kugelman
  • 1,751
  • 15
  • 20
  • 2
    `git pull --all` will by default *not* pull master into live, it will pull master and merge it with master, and (if existing on the server) pull live to merge into live. Did you try it? – Tobias Kienzler Jul 16 '10 at 07:56
  • Is your problem caused by a file that was not under version control before branching off live and git-added after modification to master later on? That's what happened to me before, usually it should suffice to temporarily rename that file, or if it isn't needed at *live*, use `git checkout -f` to ignore the problem - but make a backup! – Tobias Kienzler Jul 16 '10 at 10:37
  • 2
    related: http://stackoverflow.com/questions/3216360/merge-update-and-pull-git-branches-without-using-checkouts – Ciro Santilli OurBigBook.com Aug 11 '14 at 15:29
  • I'm not sure how this is related to http://stackoverflow.com/questions/3216360/merge-update-and-pull-git-branches-without-using-checkouts - that said there is a clear workflow issue here, and I think an easy fix would be to use a Fork/PR flow for live and give devs the ability to test on their own fork. Only production-ready code gets approved and merged in the repo (you make sure approvers are aware and filtering properly) while devs can commit and test on their own forks (which are some sort of branches anyway). Make sure devs cannot push directly and must go through PR/review. – Thomas Guyot-Sionnest Sep 16 '20 at 07:15
  • 1
    @ThomasGuyot-Sionnest this question is 10 years old, 4 years older than e.g. Gitlab. Things were... different... back then –  Sep 16 '20 at 07:29

5 Answers5

373

I was able to pull changes from origin/master into master while working in another branch by using this command:

git fetch origin master:master

For a deeper dive into what's going on, check out the excellent answer to this Stack Overflow question. The main take-away for me was that this command only works for a fast-forward merge.

danba
  • 103
  • 4
Jeff B
  • 4,429
  • 5
  • 18
  • 26
  • 12
    Awesome! Exactly what I was looking for - this needs to be much more prominently documented... – Markus Shepherd Jan 14 '19 at 09:22
  • 4
    You can find documentation on this here: https://git-scm.com/docs/git-fetch#_examples – c1moore Feb 08 '19 at 14:16
  • 15
    `fetch` != `pull` – D. Kovács Jul 16 '19 at 07:21
  • 9
    This does update the specified branch to the upstream branch. – sean Jan 16 '20 at 07:15
  • 10
    Add `-f` in case it's not a fast-forward, and you want to force update it: `git fetch -f origin master:master` – Diego Jan 30 '20 at 11:37
  • 1
    From my attempts using `pull` (I used `git pull origin master:master`) it also tried to merge master into my current branch which isn't what I want. Using `fetch` only changed `master` and left my current branch alone. – Jeff B Jul 02 '20 at 16:09
  • 1
    I think this is probably the canonical answer for this question: https://stackoverflow.com/questions/3216360/merge-update-and-pull-git-branches-without-using-checkouts – icc97 Aug 06 '20 at 10:17
  • Excellent @icc97, I'll include the link in my answer. – Jeff B Aug 06 '20 at 12:39
21

You can use git stash before checking out master and pulling, and after checking out live again use git stash pop (or if your git is older, git stash apply and git stash clear assuming you haven't stashed anything else)

Tobias Kienzler
  • 4,421
  • 7
  • 44
  • 76
  • 9
    `git pull --all` will fetch all remotes, but it will still try to merge a branch (or the default branch) into the current branch as well. – mipadi Jul 15 '10 at 16:21
  • @mipadi yes, but only the current branch into itself whithout trying to checkout master and causing the conflict, no? – Tobias Kienzler Jul 16 '10 at 06:13
  • It'll merge whatever branch is configured to be automatically merged into the current branch (if such a branch is configured). – mipadi Jul 16 '10 at 06:26
  • The `--all` option has nothing to do with branches. – Superole Jul 25 '13 at 08:51
  • 1
    @Superole It's documented as "fetch all remotes", which includes not only multiple repositories, but also branches. Though in hindsight, `git fetch --all` might have been a better answer – Tobias Kienzler Jul 25 '13 at 09:02
  • 3
    @TobiasKienzler It only instructs git to fetch from all configured remotes. The most common case is to have only one remote named origin. IF you happen to have more than one remote with the same branch as your current, and they are not in a fast-forward relationship to eachother, THEN using the `--all` option will give you an octopus merge of the different versions of the branch into the current! So my advice is to stay away from `--all` unless that is what you're after, because in most other cases it will give you nothing. – Superole Jul 25 '13 at 09:24
  • @Superole Good point, I edited that one out. Sorry for not having read your comment earlier... – Tobias Kienzler Sep 22 '14 at 10:53
14

Solve the problem first. They should not be pushing to a branch they have no business pushing to.

What you seem to be asking would be something like

git checkout live
git pull origin master

This will attempt a merge of the remote master and your live branch.

Josh K
  • 12,747
  • 7
  • 41
  • 58
  • The problem is that we currently have only one branch and it won't really be possible to change that since everyone is too used to SVN and not willing to learn the advantages of something new. It will only be possible to create a new branch in the live directory. Merging the remote master to the live branch is what i want to avoid as i cannot prevent anyone from pushing debug code, incomplete functions, syntax errors and anything else to the master (I'm just the junior developer after all). Thanks for your suggestion though. –  Jul 13 '10 at 14:16
  • 2
    @dbeme: You could use tarballs and patches. ;) Unless they're willing to learn git (and it's not hard at all to branch and merge) you're going to have issues. – Josh K Jul 13 '10 at 15:52
4

First off, note you never actually need a local copy of master if you aren't committing directly to it. So the simplest solution to your problem is to change this part of your workflow:

git merge master

to

git merge origin/master

Then you don't have to bother pulling down the local branch. That being said, if you prefer to have the local copy, it's conceptually easier to think of "updating master" without checking it out first, this way:

# delete your local master (normally either -d or -D should work here)
git branch -D master
# create a new copy of master from the remote copy
git branch master origin/master

And there's a faster way too, since you can force it and skip the delete:

# replace your local copy of master with it's remote version, even if it already exists
git branch -f master origin/master

Obviously, all of these commands assume you have already fetched from the latest origin beforehand. If not, perform git fetch first.

TTT
  • 683
  • 5
  • 11
  • Doesn't this use a stored copy of the remote branch, not the actual remote branch? origin/master is technically a local branch that represents the remote branch, but that doesn't mean its up to date with actual remote. As I understand it. – Keith Tyler Oct 12 '20 at 17:29
  • @KeithTyler correct. That's the reason for the last sentence. When you fetch you are updating your copy from the actual remote. – TTT Oct 12 '20 at 17:38
1

I recommend that you create a testing git repo for everyone to commit. All repos, including your live website will be clones of the testing repo. In this manner, anyone can push to testing without touching the live web site. When someone needs to update the live site, then you can pull the live site from the git testing repo. This workflow is fairly similar to SVN. For extra flexibility, I recommend using the "live" branch that you describe.

To summarize, everyone's git repo is a clone of the testing repo. The live production site is just a clone of the testing repo as well. Alternatively, testing could be a clone of live prodcution so that a "git push" always moves toward production.

Other options including adding the "live" branch to this arrangement or including a "staging" repo between testing and production. For extra security, I recommend restricting access to the live git repo and forcing people to use a secured script that does the pull to live production.

edgester
  • 172
  • 3