本地存储库上单个开发人员的 Git 工作流程

发布于 2024-09-30 01:07:00 字数 4008 浏览 12 评论 0原文

我正在尝试将个人 git 工作流程改进为更容易处理的东西。

以下是我在本文中如何使用 git 的一些背景:

  • 唯一在存储库上工作的开发人员。

  • 存储在本地计算机上的存储库的单个副本。

  • 只有两个分支“dev”和“master”。

  • 在“dev”上完成的所有工作。

我想要完成的是达到这样的程度:对“master”分支所做的唯一提交是基于已确认的稳定“dev”代码的工作生产版本。

实际上,我想做的是:

  1. 当“dev”中的所有内容都经过测试并准备就绪时,将“master”更新为“dev”分支文件树的精确克隆。

  2. 对“master”进行细微修改以更新版本号等...

  3. 提交到更新的“master”分支。

  4. 从“master”分支创建一个新标签。

我接近第一步的方法是签出“master”分支,然后运行:

'git diff master dev | git apply -'

根据我的理解,这实际上会清除“master”中的任何内容,并用“dev”的内容替换整个树。运行“git status”似乎表明这正在执行基于上面#1 的预期操作。

那么,第一个问题:这是正确的吗?

在“master”分支收到这些更新后,我运行我的脚本来更新文件中的版本号。然后,我只需运行标准的“git add”。和“git commit -a”来添加所有更改。最后,我创建一个新标签并返回“dev”分支再次开始编码。

那么,另一个问题:该过程中是否有任何东西会导致问题?

更新:我应该在第一次就提出这个问题,但我不简单地使用合并的原因是更改 master 上的版本号,然后尝试与 dev 中的更改合并会导致合并冲突。我知道它们无关紧要,但它仍然停止了该过程。我之前使用过“merge -Xtheirs {branch}”来处理它,但我也不确定。

UPDATE2:这是一些我知道不起作用的东西。我编写了一个可在 Mac OSX 上运行的 bash 脚本。第一个尝试使用合并:

#!/bin/bash -x

####################
### file: merge1 ###
####################

### clear out the old stuff so you can rerun
rm -rf .git
rm *.txt

### setup the repository
git init

### ignore merge and output files for clarity sake
echo -e "output*\nmerge*" > .gitignore
git add .gitignore

### make the intial commit and move over to dev
git commit -m "Initial commit"
git checkout -b dev

### add stuff to test1.txt in dev
echo -e "FILE1 LINE\nVERSION-XXX\nFILE1 LINE" > test1.txt
echo -e "File2 LINE\nVERSION-XXX\nFILE2 LINE" > test2.txt

### add the files and commit
git add .
git commit -m "Created test1.txt and test2.txt in dev."

### output the state of test1.
cat test1.txt > output-dev-test1-a.txt
cat test2.txt > output-dev-test2-a.txt

### move to master and do a first merge which will work
git checkout master
git merge dev

### Update the version numbers in master and commit it
sed -i "" -e 's/VERSION-XXX/VERSION-1.0/g' test*.txt
git commit -am "Updated version to 1.0 on master"

cat test1.txt > output-master-test1-a.txt
cat test2.txt > output-master-test2-a.txt

### switch back to dev and commit an update to test1.txt
git checkout dev
sed -i "" -e 's/LINE/CHANGED/' test*.txt
git commit -am "Updated content in test*.txt on dev"

### dump test1.txt for reference.
cat test1.txt > output-dev-test1-b.txt
cat test2.txt > output-dev-test2-b.txt

### swtich back to master
git checkout master

######################################################################
### BREAK
######################################################################

### this is where the merge fails because of a conflict
git merge dev

我尝试的另一种方法是使用 -Xtheirs,它看起来一开始可以工作,但它不会更新所有内容。要看到这一点,请删除上面的 BREAK 后的最后几行并将其替换为:

### merge with -Xtheirs works here. Proper version "XXX" is showing.
git merge -Xtheirs dev

### but if we update the version number one more time on master
sed -i "" -e 's/VERSION-XXX/VERSION-2.0/g' test*.txt
git commit -am "Updated version to 2.0 on master"

### dump reference file
cat test1.txt > output-master-test1-b.txt
cat test2.txt > output-master-test2-b.txt

### Now, go back to dev and change something in only one of the files
git checkout dev
sed -i "" -e 's/CHANGED/ALTERED/g' test2.txt
git commit -am "Altered only test2.txt on dev."

cat test1.txt > output-dev-test1-c.txt
cat test2.txt > output-dev-test2-c.txt


### are finally return to master and merge again
git checkout master
git merge -Xtheirs dev

### dump reference file
cat test1.txt > output-master-test1-c.txt
cat test2.txt > output-master-test2-c.txt

There are noconflicts, but 'output-master-test1-c.txt' 显示 'VERSION-2.0' 而不是 'VERSION-XXX',即想要的。发生这种情况似乎是因为文件没有发生任何更改。 “output-master-test2-c.txt”文件具有预期的“VERSION-XXX”字符串。当然,问题是尝试更新到版本 3.0 的查找和替换会在 test1-c 中丢失,因为它无法识别 VERSION 刺痛的 2.0 部分。

I'm trying to refine a personal git workflow to something a little easier to deal with.

Here's some background of how I'm using git for purposes of this post:

  • A single developer who is the only one working on the repository.

  • A single copy of the repository that is stored on the local machine.

  • Only two branches "dev" and "master".

  • All work done on "dev".

What I'm trying to accomplish is to get to the point where the only commits made to the "master" branch are working production versions based on the confrimed stable "dev" code.

Effectively, what I'm looking to do is:

  1. When everything in "dev" is tested and ready to go, update "master" to be an exact clone of the "dev" branch file tree.

  2. Make minor modifications to "master" to update version numbers, etc...

  3. Commit to the updated "master" branch.

  4. Make a new tag from the "master" branch.

The way that I'm approaching the first step is to checkout the "master" branch and then to run:

'git diff master dev | git apply -'

From what I understand, this effectively blows away anything in "master" and replaces the entire tree with the contents of "dev". Running "git status" appears to show that this is doing what's expected based on #1 above.

So, the first question: Is that correct?

After the "master" branch has received these updates, I run my script over to update version numbers in files. Then, I just run a standard "git add ." and "git commit -a" to add all the changes. Finally, I make a new tag and return to the "dev" branch to start coding again.

So, the other question: Is there anything in that process that is going to cause issues?

UPDATE: I should have put this in the first time, but the reason I'm not simply using merge is that changing the version number on master and then trying to merge with changes in dev causes merge conflicts. I know they are irrelevant, but it still stops the process. I've used "merge -Xtheirs {branch}" before to deal with it, but I'm not sure about that either.

UPDATE2: Here's some stuff that I know does not work. I've put together a bash script that works on Mac OSX. The first one attempts to use merge:

#!/bin/bash -x

####################
### file: merge1 ###
####################

### clear out the old stuff so you can rerun
rm -rf .git
rm *.txt

### setup the repository
git init

### ignore merge and output files for clarity sake
echo -e "output*\nmerge*" > .gitignore
git add .gitignore

### make the intial commit and move over to dev
git commit -m "Initial commit"
git checkout -b dev

### add stuff to test1.txt in dev
echo -e "FILE1 LINE\nVERSION-XXX\nFILE1 LINE" > test1.txt
echo -e "File2 LINE\nVERSION-XXX\nFILE2 LINE" > test2.txt

### add the files and commit
git add .
git commit -m "Created test1.txt and test2.txt in dev."

### output the state of test1.
cat test1.txt > output-dev-test1-a.txt
cat test2.txt > output-dev-test2-a.txt

### move to master and do a first merge which will work
git checkout master
git merge dev

### Update the version numbers in master and commit it
sed -i "" -e 's/VERSION-XXX/VERSION-1.0/g' test*.txt
git commit -am "Updated version to 1.0 on master"

cat test1.txt > output-master-test1-a.txt
cat test2.txt > output-master-test2-a.txt

### switch back to dev and commit an update to test1.txt
git checkout dev
sed -i "" -e 's/LINE/CHANGED/' test*.txt
git commit -am "Updated content in test*.txt on dev"

### dump test1.txt for reference.
cat test1.txt > output-dev-test1-b.txt
cat test2.txt > output-dev-test2-b.txt

### swtich back to master
git checkout master

######################################################################
### BREAK
######################################################################

### this is where the merge fails because of a conflict
git merge dev

The other way I tried this was with -Xtheirs, which looks like it works at first, but it doesn't update everything. To see that, remove the last few lines after the BREAK above and replace them with:

### merge with -Xtheirs works here. Proper version "XXX" is showing.
git merge -Xtheirs dev

### but if we update the version number one more time on master
sed -i "" -e 's/VERSION-XXX/VERSION-2.0/g' test*.txt
git commit -am "Updated version to 2.0 on master"

### dump reference file
cat test1.txt > output-master-test1-b.txt
cat test2.txt > output-master-test2-b.txt

### Now, go back to dev and change something in only one of the files
git checkout dev
sed -i "" -e 's/CHANGED/ALTERED/g' test2.txt
git commit -am "Altered only test2.txt on dev."

cat test1.txt > output-dev-test1-c.txt
cat test2.txt > output-dev-test2-c.txt


### are finally return to master and merge again
git checkout master
git merge -Xtheirs dev

### dump reference file
cat test1.txt > output-master-test1-c.txt
cat test2.txt > output-master-test2-c.txt

There are no conflicts, but 'output-master-test1-c.txt' shows 'VERSION-2.0' instead of 'VERSION-XXX' which is desired. This appears to have happened because there were no changes to the file. The 'output-master-test2-c.txt' file has the expected 'VERSION-XXX' sting. The problem, of course, is that the find and replace that tried to update to version 3.0 would miss in test1-c because it wouldn't recognize the 2.0 part of the VERSION sting.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

忘羡 2024-10-07 01:07:00

您应该使用真正的合并而不是 diff/apply hack。这很简单,

[master]$ git merge dev

当您在 master 分支上运行它时(如提示符所示),您将合并来自 dev 的所有更改。之后您可以更新版本号、提交并创建标签,

[master]$ git commit -a -m "New version number."
[master]$ git tag version-1.x

就这么简单。

事实上,你根本不需要主分支,你可以基于 dev 创建一个短暂的发布分支,在那里创建一个标签,然后删除该分支。

[dev]$ git checkout -b release dev
[release]$ git commit -a -m "New version number."
[release]$ git tag version-1.x
[release]$ git checkout dev
[dev]$ git branch -d release

You should use real merges instead of the diff/apply hack. This is as simple as

[master]$ git merge dev

When you run this on the master branch (shown in prompt) you will merge in all changes from dev. Afterwards you can update the version number, commit and create a tag

[master]$ git commit -a -m "New version number."
[master]$ git tag version-1.x

It's as simple as that.

In fact you don't really need a master branch at all, you can create a short lived release branch based on dev, create a tag there and delete the branch afterwards.

[dev]$ git checkout -b release dev
[release]$ git commit -a -m "New version number."
[release]$ git tag version-1.x
[release]$ git checkout dev
[dev]$ git branch -d release
情话难免假 2024-10-07 01:07:00

我做了一些非常类似的事情(仅当我是自己软件的唯一开发人员时)......

我只在主分支上工作。在不同的“版本”中,我创建了一个悬空分支。

这使我只需检查即可返回到任何以前的版本。

A - B - C - D - E - F
     \               \
      1.0             1.1

很简单,而且效果很好,足以满足我的需要。

如果我需要对以前的版本进行一些错误修复,我只需在该分支上工作并完成它们即可。

I do something very similar (only when I'm the sole developer on my own software)...

I work SOLELY on the master branch. And at different 'versions', I create a dangling branch.

This enables me to get back to any previous version just by checking it out.

A - B - C - D - E - F
     \               \
      1.0             1.1

Easy and works good enough for my needs.

If I need to do some bug fixes to previous versions, i just work off of that branch and get them done.

还在原地等你 2024-10-07 01:07:00

我想出了另一种方法来解决这个问题,我认为它可以满足我需要的一切。其核心是在 master 上执行以下操作:

### pull the diff to make sure there are no conflict
git diff master dev | git apply -

### do merge without commit to make branch tree behave
git merge --no-commit --no-ff -s ours dev

### update the version numbers
sed -i "" -e "s/VERSION-XXX/VERSION-$1/g" *.txt

### now, add everything to master and commit
git add . 
git commit -m "Master commit $1"

这确保“dev”中的所有版本号保留为“XXX”,但在“master”中的所有文件中正确更新。另外,在 gitk 中查看“master”分支的历史记录,您可以看到特定的“dev”版本被添加到的位置。例如:

dev:      d1----d2----d3----d4----d5
         /  \           \     \
master: x    m1          m2    m3

这棵树就是我正在寻找的树,它让我更容易理解围绕到底发生了什么。

这是一个 bash 脚本(在 Mac OSX 上编写,以防万一),我用它来测试并解决这个问题。如果有兴趣尝试其他策略,您应该能够更新“doMerge”函数并运行脚本来看看会发生什么。

#!/bin/bash

######################################################################
# Setup functions
######################################################################

function doMerge {

  ### add everything in dev
  git add .
  git commit -m "Commiting dev $1"

  ### switch to master
  git checkout master

  ### pull the diff to make sure there are no conflict
  git diff master dev | git apply -

  ### do merge without commit to make branch tree behave
  git merge --no-commit --no-ff -s ours dev

  ### update the version numbers
  sed -i "" -e "s/VERSION-XXX/VERSION-$1/g" *.txt

  ### now, add everything to master and commit
  git add . 
  git commit -m "Master commit $1"

  git tag -m "Created tag v-$a" -a "v-$1"

  ### and then switch back to dev so you are ready to work
  git checkout dev

}


### this just lets you see what's going on in the output
function showReport {

  echo "############################################################"
  echo "##### 'dev' branch files #####"
  echo "############################################################"

  DEVCNT=1
  while [ $DEVCNT -lt 4 ]; do
    cat $DEVCNT.txt
    echo "############################################################"
    let DEVCNT=DEVCNT+1 
  done

  git checkout master


  echo "############################################################"
  echo "##### 'master' branch files #####"
  echo "############################################################"

  MASTCNT=1
  while [ $MASTCNT -lt 4 ]; do
    cat $MASTCNT.txt
    echo "############################################################"
    let MASTCNT=MASTCNT+1 
  done
  echo ""

  git checkout dev

}


######################################################################
# Main
######################################################################

### clear out the old stuff so you can rerun
rm -rf .git
rm *.txt

### setup the repository
git init

### ignore merge and output files for clarity sake
echo "check-history" > .gitignore
git add .gitignore

git commit -m "added .gitignore"

### switch to dev
git checkout -b dev

### add some files
COUNTER=1
while [  $COUNTER -lt 10 ]; do
  echo "File $COUNTER - VERSION-XXX" > $COUNTER.txt
  echo "The quick brown fox jumps over the lazy dog" >> $COUNTER.txt
  let COUNTER=COUNTER+1 
done

### run the diff/apply/merge strategy and show the results
doMerge 1; showReport


echo "File 2 - VERSION-XXX" > 2.txt
echo "New Data" >> 2.txt

git commit -am "dev tmp commit 1"

echo "Additional data" >> 1.txt
echo "Additional data" >> 2.txt

doMerge 2; showReport

sed -i "" -e 's/quick/EXTREMELY FAST/' 3.txt

doMerge 3; showReport

据我所知,这是有效的。我会尝试一下,如果我发现了什么,我会在这里报告。当然,如果您知道的话,我也对其他不那么麻烦的方法感兴趣。

I've come up with another way to approach this that I think does everything I need. The heart of it is to do the following on master:

### pull the diff to make sure there are no conflict
git diff master dev | git apply -

### do merge without commit to make branch tree behave
git merge --no-commit --no-ff -s ours dev

### update the version numbers
sed -i "" -e "s/VERSION-XXX/VERSION-$1/g" *.txt

### now, add everything to master and commit
git add . 
git commit -m "Master commit $1"

This makes sure that all the version numbers in "dev" stay at "XXX" but are updated properly across all files in "master". Also, looking in gitk at the history of the "master" branch, you can see where the specific "dev" versions were added in. For example:

dev:      d1----d2----d3----d4----d5
         /  \           \     \
master: x    m1          m2    m3

This tree is what I was looking for and makes it easier for me to get my head around exactly what is going on.

Here is a bash script (written on Mac OSX in case that matter) that I used to test and figure this out. If there is interest in trying other strategies, you should be able to just update the "doMerge" function and run the script to see what happens.

#!/bin/bash

######################################################################
# Setup functions
######################################################################

function doMerge {

  ### add everything in dev
  git add .
  git commit -m "Commiting dev $1"

  ### switch to master
  git checkout master

  ### pull the diff to make sure there are no conflict
  git diff master dev | git apply -

  ### do merge without commit to make branch tree behave
  git merge --no-commit --no-ff -s ours dev

  ### update the version numbers
  sed -i "" -e "s/VERSION-XXX/VERSION-$1/g" *.txt

  ### now, add everything to master and commit
  git add . 
  git commit -m "Master commit $1"

  git tag -m "Created tag v-$a" -a "v-$1"

  ### and then switch back to dev so you are ready to work
  git checkout dev

}


### this just lets you see what's going on in the output
function showReport {

  echo "############################################################"
  echo "##### 'dev' branch files #####"
  echo "############################################################"

  DEVCNT=1
  while [ $DEVCNT -lt 4 ]; do
    cat $DEVCNT.txt
    echo "############################################################"
    let DEVCNT=DEVCNT+1 
  done

  git checkout master


  echo "############################################################"
  echo "##### 'master' branch files #####"
  echo "############################################################"

  MASTCNT=1
  while [ $MASTCNT -lt 4 ]; do
    cat $MASTCNT.txt
    echo "############################################################"
    let MASTCNT=MASTCNT+1 
  done
  echo ""

  git checkout dev

}


######################################################################
# Main
######################################################################

### clear out the old stuff so you can rerun
rm -rf .git
rm *.txt

### setup the repository
git init

### ignore merge and output files for clarity sake
echo "check-history" > .gitignore
git add .gitignore

git commit -m "added .gitignore"

### switch to dev
git checkout -b dev

### add some files
COUNTER=1
while [  $COUNTER -lt 10 ]; do
  echo "File $COUNTER - VERSION-XXX" > $COUNTER.txt
  echo "The quick brown fox jumps over the lazy dog" >> $COUNTER.txt
  let COUNTER=COUNTER+1 
done

### run the diff/apply/merge strategy and show the results
doMerge 1; showReport


echo "File 2 - VERSION-XXX" > 2.txt
echo "New Data" >> 2.txt

git commit -am "dev tmp commit 1"

echo "Additional data" >> 1.txt
echo "Additional data" >> 2.txt

doMerge 2; showReport

sed -i "" -e 's/quick/EXTREMELY FAST/' 3.txt

doMerge 3; showReport

From what I can tell, this works. I'll be giving it a shot and will report back here if I discover something. Of course, if you know of any, I'm also interested in other ways to do this that are less hacky.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文